blob: ef5c69a78ab308838ab1da5dd3ca9acd5eb1391e [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
Alvin Wangbf99c582019-10-29 16:40:05 +080019import simplejson
Justin Thalerf9aee3e2017-12-05 12:11:09 -060020import getpass
21import json
22import os
23import urllib3
24import time, datetime
Justin Thalerf9aee3e2017-12-05 12:11:09 -060025import binascii
26import subprocess
27import platform
28import zipfile
Justin Thaler22b1bb52018-03-15 13:31:32 -050029import tarfile
30import tempfile
31import hashlib
Justin Thalera6b5df72018-07-16 11:10:07 -050032import re
Justin Thaler24d4efa2018-11-08 22:48:10 -060033import uuid
Ravi Tejad8be0b42020-03-18 14:31:46 -050034import ssl
35import socket
36import select
37import http.client
38from subprocess import check_output
Justin Thalerf9aee3e2017-12-05 12:11:09 -060039
Ravi Tejad8be0b42020-03-18 14:31:46 -050040
41MAX_NBD_PACKET_SIZE = 131088
Matt Spinler220c3c42019-01-04 15:09:29 -060042jsonHeader = {'Content-Type' : 'application/json'}
43xAuthHeader = {}
Justin Thaler27197622019-01-23 14:42:11 -060044baseTimeout = 60
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -050045serverTypeMap = {
46 'ActiveDirectory' : 'active_directory',
47 'OpenLDAP' : 'openldap'
48 }
Matt Spinler220c3c42019-01-04 15:09:29 -060049
Ravi Tejad8be0b42020-03-18 14:31:46 -050050class NBDPipe:
51
52 def openHTTPSocket(self,args):
53
54 try:
55 _create_unverified_https_context = ssl._create_unverified_context
56 except AttributeError:
57 # Legacy Python that doesn't verify HTTPS certificates by default
58 pass
59 else:
60 # Handle target environment that doesn't support HTTPS verification
61 ssl._create_default_https_context = _create_unverified_https_context
62
63
64 token = gettoken(args)
65 self.conn = http.client.HTTPSConnection(args.host,port=443)
66 URI = "/redfish/v1/Systems/system/LogServices/SystemDump/Entries/"+str(args.dumpNum)+"/Actions/Oem/OpenBmc/LogEntry.DownloadLog"
67 self.conn.request("POST",URI, headers={"X-Auth-Token":token})
68
69 def openTCPSocket(self):
70 # Create a TCP/IP socket
71 self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
72 # Connect the socket to the port where the server is listening
73 server_address = ('localhost', 1043)
74 self.tcp.connect(server_address)
75
76 def waitformessage(self):
77 inputs = [self.conn.sock,self.tcp]
78 outputs = []
79 message_queues = {}
80 while True:
81 readable, writable, exceptional = select.select(
82 inputs, outputs, inputs)
83
84 for s in readable:
85 if s is self.conn.sock:
86
87 data = self.conn.sock.recv(MAX_NBD_PACKET_SIZE)
88 print("<<HTTP")
89 #print(len(data))
90 if data:
91 self.tcp.send(data)
92 else:
93 print ("BMC Closed the connection")
94 self.conn.close()
95 self.tcp.close()
96 sys.exit(1)
97 elif s is self.tcp:
98 data = self.tcp.recv(MAX_NBD_PACKET_SIZE)
99 print(">>TCP")
100 #print(len(data));
101 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):
114 url = "https://"+host+"/redfish/v1/Systems/system/LogServices/SystemDump/Entries/"+str(args.dumpNum)
115 print(url)
116 try:
117 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
118 if resp.status_code==200:
119 size = resp.json()["Oem"]["OpenBmc"]['SizeInB']
120 print(size)
121 return size
122 else:
123 return "Failed get Size"
124 except(requests.exceptions.Timeout):
125 return connectionErrHandler(args.json, "Timeout", None)
126
127 except(requests.exceptions.ConnectionError) as err:
128 return connectionErrHandler(args.json, "ConnectionError", err)
129
130def gettoken(args):
131 mysess = requests.session()
132 resp = mysess.post('https://'+args.host+'/login', headers=jsonHeader,json={"data":[args.user,args.PW]},verify=False)
133 if resp.status_code == 200:
134 cookie = resp.headers['Set-Cookie']
135 match = re.search('SESSION=(\w+);', cookie)
136 return match.group(1)
137
138
139
140def get_pid(name):
141 try:
142 pid = map(int, check_output(["pidof", "-s",name]))
143 except Exception:
144 pid = 0
145
146 return pid
147
148def findThisProcess( process_name ):
149 ps = subprocess.Popen("ps -eaf | grep "+process_name, shell=True, stdout=subprocess.PIPE)
150 output = ps.stdout.read()
151 ps.stdout.close()
152 ps.wait()
153 pid = get_pid(process_name)
154 print(pid)
155 return output
156
157def isThisProcessRunning( process_name ):
158 pid = get_pid(process_name)
159 if (pid == 0 ):
160 return False
161 else:
162 return True
163
164def NBDSetup(host,args,session):
165 user=os.getenv("SUDO_USER")
166 if user is None:
167 path = os.getcwd()
168 nbdServerPath = path + "/nbd-server"
169 print(nbdServerPath,os.path.exists(nbdServerPath))
170 if not os.path.exists(nbdServerPath):
171 print("Error: this program did not run as sudo!\nplease copy nbd-server to current directory and run script again")
172 exit()
173
174 if isThisProcessRunning('nbd-server') == True:
175 print("nbd-server already Running! killing the nbd-server")
176 os.system('killall nbd-server')
177
178 if (args.dumpSaveLoc is not None):
179 if(os.path.exists(args.dumpSaveLoc)):
180 print("Error: File already exists.")
181 exit()
182
183 fp= open(args.dumpSaveLoc,"w")
184 sizeInBytes = getsize(host,args,session)
185 #Round off size to mutiples of 1024
186 size = int(sizeInBytes)
187 print(size)
188 mod = size % 1024
189 if mod :
190 roundoff = 1024 - mod
191 size = size + roundoff
192
193 cmd = 'chmod 777 ' + args.dumpSaveLoc
194 os.system(cmd)
195
196 #Run truncate to create file with given size
197 cmd = 'truncate -s ' + str(size) + ' '+ args.dumpSaveLoc
198 os.system(cmd)
199
200 if user is None:
201 cmd = './nbd-server 1043 '+ args.dumpSaveLoc
202 else:
203 cmd = 'nbd-server 1043 '+ args.dumpSaveLoc
204 os.system(cmd)
205
206
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600207def hilight(textToColor, color, bold):
Justin Thalere412dc22018-01-12 16:28:24 -0600208 """
209 Used to add highlights to various text for displaying in a terminal
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600210
Justin Thalere412dc22018-01-12 16:28:24 -0600211 @param textToColor: string, the text to be colored
212 @param color: string, used to color the text red or green
213 @param bold: boolean, used to bold the textToColor
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600214 @return: Buffered reader containing the modified string.
215 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600216 if(sys.platform.__contains__("win")):
217 if(color == "red"):
218 os.system('color 04')
219 elif(color == "green"):
220 os.system('color 02')
221 else:
222 os.system('color') #reset to default
223 return textToColor
224 else:
225 attr = []
226 if(color == "red"):
227 attr.append('31')
228 elif(color == "green"):
229 attr.append('32')
230 else:
231 attr.append('0')
232 if bold:
233 attr.append('1')
234 else:
235 attr.append('0')
236 return '\x1b[%sm%s\x1b[0m' % (';'.join(attr),textToColor)
237
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600238def connectionErrHandler(jsonFormat, errorStr, err):
Justin Thalere412dc22018-01-12 16:28:24 -0600239 """
240 Error handler various connection errors to bmcs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600241
242 @param jsonFormat: boolean, used to output in json format with an error code.
Justin Thalere412dc22018-01-12 16:28:24 -0600243 @param errorStr: string, used to color the text red or green
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600244 @param err: string, the text from the exception
245 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600246 if errorStr == "Timeout":
247 if not jsonFormat:
248 return("FQPSPIN0000M: Connection timed out. Ensure you have network connectivity to the bmc")
249 else:
Justin Thaler115bca72018-05-25 19:29:08 -0500250 conerror = {}
251 conerror['CommonEventID'] = 'FQPSPIN0000M'
252 conerror['sensor']="N/A"
253 conerror['state']="N/A"
254 conerror['additionalDetails'] = "N/A"
255 conerror['Message']="Connection timed out. Ensure you have network connectivity to the BMC"
256 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."
257 conerror['Serviceable']="Yes"
258 conerror['CallHomeCandidate']= "No"
259 conerror['Severity'] = "Critical"
260 conerror['EventType'] = "Communication Failure/Timeout"
261 conerror['VMMigrationFlag'] = "Yes"
262 conerror["AffectedSubsystem"] = "Interconnect (Networking)"
263 conerror["timestamp"] = str(int(time.time()))
264 conerror["UserAction"] = "Verify network connectivity between the two systems and the bmc is functional."
265 eventdict = {}
266 eventdict['event0'] = conerror
267 eventdict['numAlerts'] = '1'
Justin Thaler115bca72018-05-25 19:29:08 -0500268 errorMessageStr = errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600269 return(errorMessageStr)
270 elif errorStr == "ConnectionError":
271 if not jsonFormat:
272 return("FQPSPIN0001M: " + str(err))
273 else:
Justin Thaler115bca72018-05-25 19:29:08 -0500274 conerror = {}
275 conerror['CommonEventID'] = 'FQPSPIN0001M'
276 conerror['sensor']="N/A"
277 conerror['state']="N/A"
278 conerror['additionalDetails'] = str(err)
279 conerror['Message']="Connection Error. View additional details for more information"
280 conerror['LengthyDescription'] = "A connection error to the specified BMC occurred and additional details are provided. Review these details to resolve the issue."
281 conerror['Serviceable']="Yes"
282 conerror['CallHomeCandidate']= "No"
283 conerror['Severity'] = "Critical"
284 conerror['EventType'] = "Communication Failure/Timeout"
285 conerror['VMMigrationFlag'] = "Yes"
286 conerror["AffectedSubsystem"] = "Interconnect (Networking)"
287 conerror["timestamp"] = str(int(time.time()))
288 conerror["UserAction"] = "Correct the issue highlighted in additional details and try again"
289 eventdict = {}
290 eventdict['event0'] = conerror
291 eventdict['numAlerts'] = '1'
Justin Thaler115bca72018-05-25 19:29:08 -0500292 errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600293 return(errorMessageStr)
Justin Thaler115bca72018-05-25 19:29:08 -0500294
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600295 else:
296 return("Unknown Error: "+ str(err))
297
Justin Thalere412dc22018-01-12 16:28:24 -0600298
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600299def setColWidth(keylist, numCols, dictForOutput, colNames):
Justin Thalere412dc22018-01-12 16:28:24 -0600300 """
301 Sets the output width of the columns to display
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600302
303 @param keylist: list, list of strings representing the keys for the dictForOutput
Justin Thalere412dc22018-01-12 16:28:24 -0600304 @param numcols: the total number of columns in the final output
305 @param dictForOutput: dictionary, contains the information to print to the screen
306 @param colNames: list, The strings to use for the column headings, in order of the keylist
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600307 @return: A list of the column widths for each respective column.
Justin Thalere412dc22018-01-12 16:28:24 -0600308 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600309 colWidths = []
310 for x in range(0, numCols):
311 colWidths.append(0)
312 for key in dictForOutput:
313 for x in range(0, numCols):
314 colWidths[x] = max(colWidths[x], len(str(dictForOutput[key][keylist[x]])))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600315
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600316 for x in range(0, numCols):
317 colWidths[x] = max(colWidths[x], len(colNames[x])) +2
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600318
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600319 return colWidths
320
321def loadPolicyTable(pathToPolicyTable):
Justin Thalere412dc22018-01-12 16:28:24 -0600322 """
323 loads a json based policy table into a dictionary
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600324
Justin Thalere412dc22018-01-12 16:28:24 -0600325 @param value: boolean, the value to convert
326 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600327 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600328 policyTable = {}
329 if(os.path.exists(pathToPolicyTable)):
330 with open(pathToPolicyTable, 'r') as stream:
331 try:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600332 contents =json.load(stream)
333 policyTable = contents['events']
Justin Thalere412dc22018-01-12 16:28:24 -0600334 except Exception as err:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600335 print(err)
336 return policyTable
337
Justin Thalere412dc22018-01-12 16:28:24 -0600338
339def boolToString(value):
340 """
341 converts a boolean value to a human readable string value
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600342
Justin Thalere412dc22018-01-12 16:28:24 -0600343 @param value: boolean, the value to convert
344 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600345 """
Justin Thalere412dc22018-01-12 16:28:24 -0600346 if(value):
347 return "Yes"
348 else:
349 return "No"
350
Justin Thalera6b5df72018-07-16 11:10:07 -0500351def stringToInt(text):
352 """
353 returns an integer if the string can be converted, otherwise returns the string
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600354
Justin Thalera6b5df72018-07-16 11:10:07 -0500355 @param text: the string to try to convert to an integer
356 """
357 if text.isdigit():
358 return int(text)
359 else:
360 return text
Justin Thalere412dc22018-01-12 16:28:24 -0600361
Justin Thalera6b5df72018-07-16 11:10:07 -0500362def naturalSort(text):
363 """
364 provides a way to naturally sort a list
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600365
Justin Thalera6b5df72018-07-16 11:10:07 -0500366 @param text: the key to convert for sorting
367 @return list containing the broken up string parts by integers and strings
368 """
369 stringPartList = []
370 for c in re.split('(\d+)', text):
371 stringPartList.append(stringToInt(c))
372 return stringPartList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600373
Justin Thalere412dc22018-01-12 16:28:24 -0600374def tableDisplay(keylist, colNames, output):
375 """
376 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600377
Justin Thalere412dc22018-01-12 16:28:24 -0600378 @param keylist: list, keys for the output dictionary, ordered by colNames
379 @param colNames: Names for the Table of the columns
380 @param output: The dictionary of data to display
381 @return: Session object
382 """
383 colWidth = setColWidth(keylist, len(colNames), output, colNames)
384 row = ""
385 outputText = ""
386 for i in range(len(colNames)):
387 if (i != 0): row = row + "| "
388 row = row + colNames[i].ljust(colWidth[i])
389 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600390
Justin Thalera6b5df72018-07-16 11:10:07 -0500391 output_keys = list(output.keys())
392 output_keys.sort(key=naturalSort)
393 for key in output_keys:
Justin Thalere412dc22018-01-12 16:28:24 -0600394 row = ""
Justin Thaler8fe0c732018-07-24 14:32:35 -0500395 for i in range(len(keylist)):
Justin Thalere412dc22018-01-12 16:28:24 -0600396 if (i != 0): row = row + "| "
397 row = row + output[key][keylist[i]].ljust(colWidth[i])
398 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600399
Justin Thalere412dc22018-01-12 16:28:24 -0600400 return outputText
401
Justin Thaler22b1bb52018-03-15 13:31:32 -0500402def checkFWactivation(host, args, session):
403 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600404 Checks the software inventory for an image that is being activated.
405
Justin Thaler22b1bb52018-03-15 13:31:32 -0500406 @return: True if an image is being activated, false is no activations are happening
407 """
408 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thaler22b1bb52018-03-15 13:31:32 -0500409 try:
Justin Thaler27197622019-01-23 14:42:11 -0600410 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -0500411 except(requests.exceptions.Timeout):
412 print(connectionErrHandler(args.json, "Timeout", None))
413 return(True)
414 except(requests.exceptions.ConnectionError) as err:
415 print( connectionErrHandler(args.json, "ConnectionError", err))
416 return True
Justin Thaler3a5771b2019-01-23 14:31:52 -0600417 fwInfo = resp.json()['data']
Justin Thaler22b1bb52018-03-15 13:31:32 -0500418 for key in fwInfo:
419 if 'Activation' in fwInfo[key]:
420 if 'Activating' in fwInfo[key]['Activation'] or 'Activating' in fwInfo[key]['RequestedActivation']:
421 return True
422 return False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600423
Joy Onyerikwu182c3a32019-10-15 08:33:59 -0500424def login(host, username, pw,jsonFormat, allowExpiredPassword):
Justin Thalere412dc22018-01-12 16:28:24 -0600425 """
426 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600427
Justin Thalere412dc22018-01-12 16:28:24 -0600428 @param host: string, the hostname or IP address of the bmc to log into
429 @param username: The user name for the bmc to log into
430 @param pw: The password for the BMC to log into
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600431 @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 -0500432 @param allowExpiredPassword: true, if the requested operation should
433 be allowed when the password is expired
Justin Thalere412dc22018-01-12 16:28:24 -0600434 @return: Session object
435 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600436 if(jsonFormat==False):
437 print("Attempting login...")
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600438 mysess = requests.session()
439 try:
Justin Thaler27197622019-01-23 14:42:11 -0600440 r = mysess.post('https://'+host+'/login', headers=jsonHeader, json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
Sunitha Harish336cda22019-07-23 02:02:52 -0500441 if r.status_code == 200:
442 cookie = r.headers['Set-Cookie']
443 match = re.search('SESSION=(\w+);', cookie)
444 if match:
445 xAuthHeader['X-Auth-Token'] = match.group(1)
446 jsonHeader.update(xAuthHeader)
447 loginMessage = json.loads(r.text)
448 if (loginMessage['status'] != "ok"):
449 print(loginMessage["data"]["description"].encode('utf-8'))
450 sys.exit(1)
Joy Onyerikwu182c3a32019-10-15 08:33:59 -0500451 if (('extendedMessage' in r.json()) and
452 ('The password for this account must be changed' in r.json()['extendedMessage'])):
453 if not allowExpiredPassword:
454 print("The password for this system has expired and must be changed"+
455 "\nsee openbmctool.py set_password --help")
456 logout(host, username, pw, mysess, jsonFormat)
457 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600458# if(sys.version_info < (3,0)):
459# urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
460# if sys.version_info >= (3,0):
461# requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Sunitha Harish336cda22019-07-23 02:02:52 -0500462 return mysess
463 else:
464 return None
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600465 except(requests.exceptions.Timeout):
Justin Thaler115bca72018-05-25 19:29:08 -0500466 return (connectionErrHandler(jsonFormat, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600467 except(requests.exceptions.ConnectionError) as err:
Justin Thaler115bca72018-05-25 19:29:08 -0500468 return (connectionErrHandler(jsonFormat, "ConnectionError", err))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600469
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600470
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600471def logout(host, username, pw, session, jsonFormat):
Justin Thalere412dc22018-01-12 16:28:24 -0600472 """
473 Logs out of the bmc and terminates the session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600474
Justin Thalere412dc22018-01-12 16:28:24 -0600475 @param host: string, the hostname or IP address of the bmc to log out of
476 @param username: The user name for the bmc to log out of
477 @param pw: The password for the BMC to log out of
478 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600479 @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true.
480 """
Justin Thalere412dc22018-01-12 16:28:24 -0600481 try:
Justin Thaler27197622019-01-23 14:42:11 -0600482 r = session.post('https://'+host+'/logout', headers=jsonHeader,json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600483 except(requests.exceptions.Timeout):
484 print(connectionErrHandler(jsonFormat, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600485
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600486 if(jsonFormat==False):
Matt Spinlereae05b02019-01-24 12:59:34 -0600487 if r.status_code == 200:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600488 print('User ' +username + ' has been logged out')
489
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600490
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600491def fru(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600492 """
493 prints out the system inventory. deprecated see fruPrint and fruList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600494
Justin Thalere412dc22018-01-12 16:28:24 -0600495 @param host: string, the hostname or IP address of the bmc
496 @param args: contains additional arguments used by the fru sub command
497 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600498 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
499 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600500 #url="https://"+host+"/org/openbmc/inventory/system/chassis/enumerate"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600501
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600502 #print(url)
503 #res = session.get(url, headers=httpHeader, verify=False)
504 #print(res.text)
505 #sample = res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600506
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600507 #inv_list = json.loads(sample)["data"]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600508
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600509 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600510 try:
Justin Thaler27197622019-01-23 14:42:11 -0600511 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600512 except(requests.exceptions.Timeout):
513 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600514
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600515 sample = res.text
516# inv_list.update(json.loads(sample)["data"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600517#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600518# #determine column width's
519# colNames = ["FRU Name", "FRU Type", "Has Fault", "Is FRU", "Present", "Version"]
520# colWidths = setColWidth(["FRU Name", "fru_type", "fault", "is_fru", "present", "version"], 6, inv_list, colNames)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600521#
522# 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 -0600523# "Present".ljust(colWidths[4]) + "Version".ljust(colWidths[5]))
524# format the output
525# for key in sorted(inv_list.keys()):
526# keyParts = key.split("/")
527# isFRU = "True" if (inv_list[key]["is_fru"]==1) else "False"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600528#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600529# fruEntry = (keyParts[len(keyParts) - 1].ljust(colWidths[0]) + inv_list[key]["fru_type"].ljust(colWidths[1])+
530# inv_list[key]["fault"].ljust(colWidths[2])+isFRU.ljust(colWidths[3])+
531# inv_list[key]["present"].ljust(colWidths[4])+ inv_list[key]["version"].ljust(colWidths[5]))
532# if(isTTY):
533# if(inv_list[key]["is_fru"] == 1):
534# color = "green"
535# bold = True
536# else:
537# color='black'
538# bold = False
539# fruEntry = hilight(fruEntry, color, bold)
540# print (fruEntry)
541 return sample
Justin Thalere412dc22018-01-12 16:28:24 -0600542
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600543def fruPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600544 """
545 prints out all inventory
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600546
Justin Thalere412dc22018-01-12 16:28:24 -0600547 @param host: string, the hostname or IP address of the bmc
548 @param args: contains additional arguments used by the fru sub command
549 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600550 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
551 @return returns the total fru list.
552 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600553 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600554 try:
Justin Thaler27197622019-01-23 14:42:11 -0600555 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600556 except(requests.exceptions.Timeout):
557 return(connectionErrHandler(args.json, "Timeout", None))
558
Justin Thaler3a5771b2019-01-23 14:31:52 -0600559 frulist={}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600560# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600561 if res.status_code==200:
562 frulist['Hardware'] = res.json()['data']
563 else:
564 if not args.json:
565 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
566 else:
567 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600568 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600569 try:
Justin Thaler27197622019-01-23 14:42:11 -0600570 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600571 except(requests.exceptions.Timeout):
572 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600573# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600574 if res.status_code==200:
575 frulist['Software'] = res.json()['data']
576 else:
577 if not args.json():
578 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
579 else:
580 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600581 return frulist
582
Justin Thalere412dc22018-01-12 16:28:24 -0600583
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600584def fruList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600585 """
586 prints out all inventory or only a specific specified item
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600587
Justin Thalere412dc22018-01-12 16:28:24 -0600588 @param host: string, the hostname or IP address of the bmc
589 @param args: contains additional arguments used by the fru sub command
590 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600591 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
592 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600593 if(args.items==True):
594 return fruPrint(host, args, session)
595 else:
Justin Thalere412dc22018-01-12 16:28:24 -0600596 return fruPrint(host, args, session)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600597
598
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600599
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600600def fruStatus(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600601 """
602 prints out the status of all FRUs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600603
Justin Thalere412dc22018-01-12 16:28:24 -0600604 @param host: string, the hostname or IP address of the bmc
605 @param args: contains additional arguments used by the fru sub command
606 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600607 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
608 """
Justin Thalere412dc22018-01-12 16:28:24 -0600609 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600610 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600611 res = session.get(url, headers=jsonHeader, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -0600612 except(requests.exceptions.Timeout):
613 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600614# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600615 frulist = res.json()['data']
Justin Thalere412dc22018-01-12 16:28:24 -0600616 frus = {}
617 for key in frulist:
618 component = frulist[key]
619 isFru = False
620 present = False
621 func = False
622 hasSels = False
623 keyPieces = key.split('/')
624 fruName = keyPieces[-1]
625 if 'core' in fruName: #associate cores to cpus
626 fruName = keyPieces[-2] + '-' + keyPieces[-1]
627 if 'Functional' in component:
628 if('Present' in component):
Justin Thalere412dc22018-01-12 16:28:24 -0600629 if 'FieldReplaceable' in component:
630 if component['FieldReplaceable'] == 1:
631 isFru = True
632 if "fan" in fruName:
633 isFru = True;
634 if component['Present'] == 1:
635 present = True
636 if component['Functional'] == 1:
637 func = True
638 if ((key + "/fault") in frulist):
639 hasSels = True;
640 if args.verbose:
641 if hasSels:
642 loglist = []
643 faults = frulist[key+"/fault"]['endpoints']
644 for item in faults:
645 loglist.append(item.split('/')[-1])
646 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
647 else:
648 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
649 else:
650 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
Justin Thalerfb9c81c2018-07-16 11:14:37 -0500651 elif "power_supply" in fruName or "powersupply" in fruName:
Justin Thalere412dc22018-01-12 16:28:24 -0600652 if component['Present'] ==1:
653 present = True
654 isFru = True
655 if ((key + "/fault") in frulist):
656 hasSels = True;
657 if args.verbose:
658 if hasSels:
659 loglist = []
660 faults = frulist[key+"/fault"]['endpoints']
Obihörnchenff8035f2018-12-05 21:07:37 +0100661 for item in faults:
662 loglist.append(item.split('/')[-1])
Justin Thalere412dc22018-01-12 16:28:24 -0600663 frus[fruName] = {"compName": fruName, "Functional": "No", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
664 else:
665 frus[fruName] = {"compName": fruName, "Functional": "Yes", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
666 else:
667 frus[fruName] = {"compName": fruName, "Functional": boolToString(not hasSels), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
668 if not args.json:
669 if not args.verbose:
670 colNames = ["Component", "Is a FRU", "Present", "Functional", "Has Logs"]
671 keylist = ["compName", "IsFru", "Present", "Functional", "hasSEL"]
672 else:
673 colNames = ["Component", "Is a FRU", "Present", "Functional", "Assoc. Log Number(s)"]
674 keylist = ["compName", "IsFru", "Present", "Functional", "selList"]
675 return tableDisplay(keylist, colNames, frus)
676 else:
677 return str(json.dumps(frus, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600678
Justin Thalere412dc22018-01-12 16:28:24 -0600679def sensor(host, args, session):
680 """
681 prints out all sensors
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600682
Justin Thalere412dc22018-01-12 16:28:24 -0600683 @param host: string, the hostname or IP address of the bmc
684 @param args: contains additional arguments used by the sensor sub command
685 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600686 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
687 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600688 url="https://"+host+"/xyz/openbmc_project/sensors/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600689 try:
Justin Thaler27197622019-01-23 14:42:11 -0600690 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600691 except(requests.exceptions.Timeout):
692 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600693
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600694 #Get OCC status
695 url="https://"+host+"/org/open_power/control/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600696 try:
Justin Thaler27197622019-01-23 14:42:11 -0600697 occres = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600698 except(requests.exceptions.Timeout):
699 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600700 if not args.json:
701 colNames = ['sensor', 'type', 'units', 'value', 'target']
Justin Thaler3a5771b2019-01-23 14:31:52 -0600702 sensors = res.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600703 output = {}
704 for key in sensors:
705 senDict = {}
706 keyparts = key.split("/")
Matt Spinler596ef742019-09-20 08:54:36 -0500707
708 # Associations like the following also show up here:
709 # /xyz/openbmc_project/sensors/<type>/<name>/<assoc-name>
710 # Skip them.
711 # Note: keyparts[0] = '' which is why there are 7 segments.
712 if len(keyparts) > 6:
713 continue
714
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600715 senDict['sensorName'] = keyparts[-1]
716 senDict['type'] = keyparts[-2]
Justin Thalere412dc22018-01-12 16:28:24 -0600717 try:
718 senDict['units'] = sensors[key]['Unit'].split('.')[-1]
719 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500720 senDict['units'] = "N/A"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600721 if('Scale' in sensors[key]):
722 scale = 10 ** sensors[key]['Scale']
723 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600724 scale = 1
Justin Thaler22b1bb52018-03-15 13:31:32 -0500725 try:
726 senDict['value'] = str(sensors[key]['Value'] * scale)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600727 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500728 if 'value' in sensors[key]:
729 senDict['value'] = sensors[key]['value']
730 else:
731 senDict['value'] = "N/A"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600732 if 'Target' in sensors[key]:
733 senDict['target'] = str(sensors[key]['Target'])
734 else:
735 senDict['target'] = 'N/A'
736 output[senDict['sensorName']] = senDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600737
Justin Thaler3a5771b2019-01-23 14:31:52 -0600738 occstatus = occres.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600739 if '/org/open_power/control/occ0' in occstatus:
740 occ0 = occstatus["/org/open_power/control/occ0"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600741 if occ0 == 1:
742 occ0 = 'Active'
743 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600744 occ0 = 'Inactive'
745 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
746 occ1 = occstatus["/org/open_power/control/occ1"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600747 if occ1 == 1:
748 occ1 = 'Active'
749 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600750 occ1 = 'Inactive'
751 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
752 else:
753 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
754 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
755 keylist = ['sensorName', 'type', 'units', 'value', 'target']
Justin Thalere412dc22018-01-12 16:28:24 -0600756
757 return tableDisplay(keylist, colNames, output)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600758 else:
759 return res.text + occres.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600760
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600761def sel(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600762 """
763 prints out the bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600764
Justin Thalere412dc22018-01-12 16:28:24 -0600765 @param host: string, the hostname or IP address of the bmc
766 @param args: contains additional arguments used by the sel sub command
767 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600768 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
769 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600770
771 url="https://"+host+"/xyz/openbmc_project/logging/entry/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600772 try:
Justin Thaler27197622019-01-23 14:42:11 -0600773 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600774 except(requests.exceptions.Timeout):
775 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600776 return res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600777
778
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600779def parseESEL(args, eselRAW):
Justin Thalere412dc22018-01-12 16:28:24 -0600780 """
781 parses the esel data and gets predetermined search terms
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600782
Justin Thalere412dc22018-01-12 16:28:24 -0600783 @param eselRAW: string, the raw esel string from the bmc
784 @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 -0600785 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600786 eselParts = {}
787 esel_bin = binascii.unhexlify(''.join(eselRAW.split()[16:]))
788 #search terms contains the search term as the key and the return dictionary key as it's value
789 searchTerms = { 'Signature Description':'signatureDescription', 'devdesc':'devdesc',
Justin Thaler22b1bb52018-03-15 13:31:32 -0500790 'Callout type': 'calloutType', 'Procedure':'procedure', 'Sensor Type': 'sensorType'}
Justin Thaler24d4efa2018-11-08 22:48:10 -0600791 uniqueID = str(uuid.uuid4())
792 eselBinPath = tempfile.gettempdir() + os.sep + uniqueID + 'esel.bin'
Justin Thalercf1deae2018-05-25 19:35:21 -0500793 with open(eselBinPath, 'wb') as f:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600794 f.write(esel_bin)
795 errlPath = ""
796 #use the right errl file for the machine architecture
797 arch = platform.machine()
798 if(arch =='x86_64' or arch =='AMD64'):
799 if os.path.exists('/opt/ibm/ras/bin/x86_64/errl'):
800 errlPath = '/opt/ibm/ras/bin/x86_64/errl'
801 elif os.path.exists('errl/x86_64/errl'):
802 errlPath = 'errl/x86_64/errl'
803 else:
804 errlPath = 'x86_64/errl'
805 elif (platform.machine()=='ppc64le'):
806 if os.path.exists('/opt/ibm/ras/bin/ppc64le/errl'):
807 errlPath = '/opt/ibm/ras/bin/ppc64le/errl'
808 elif os.path.exists('errl/ppc64le/errl'):
809 errlPath = 'errl/ppc64le/errl'
810 else:
811 errlPath = 'ppc64le/errl'
812 else:
813 print("machine architecture not supported for parsing eSELs")
814 return eselParts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600815
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600816 if(os.path.exists(errlPath)):
Justin Thalercf1deae2018-05-25 19:35:21 -0500817 output= subprocess.check_output([errlPath, '-d', '--file='+eselBinPath]).decode('utf-8')
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600818# output = proc.communicate()[0]
819 lines = output.split('\n')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600820
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600821 if(hasattr(args, 'fullEsel')):
822 return output
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600823
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600824 for i in range(0, len(lines)):
825 lineParts = lines[i].split(':')
826 if(len(lineParts)>1): #ignore multi lines, output formatting lines, and other information
827 for term in searchTerms:
828 if(term in lineParts[0]):
829 temp = lines[i][lines[i].find(':')+1:].strip()[:-1].strip()
830 if lines[i+1].find(':') != -1:
831 if (len(lines[i+1].split(':')[0][1:].strip())==0):
832 while(len(lines[i][:lines[i].find(':')].strip())>2):
Justin Thaler43030422018-11-08 22:50:21 -0600833 #has multiple lines, process and update line counter
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600834 if((i+1) <= len(lines)):
835 i+=1
836 else:
837 i=i-1
838 break
Justin Thaler43030422018-11-08 22:50:21 -0600839 #Append the content from the next line removing the pretty display characters
840 #Finds the first colon then starts 2 characters after, then removes all whitespace
841 temp = temp + lines[i][lines[i].find(':')+2:].strip()[:-1].strip()[:-1].strip()
Justin Thaler22b1bb52018-03-15 13:31:32 -0500842 if(searchTerms[term] in eselParts):
843 eselParts[searchTerms[term]] = eselParts[searchTerms[term]] + ", " + temp
844 else:
845 eselParts[searchTerms[term]] = temp
Justin Thalercf1deae2018-05-25 19:35:21 -0500846 os.remove(eselBinPath)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600847 else:
848 print("errl file cannot be found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600849
850 return eselParts
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600851
Justin Thalere412dc22018-01-12 16:28:24 -0600852
Matt Spinler02d0dff2018-08-29 13:19:25 -0500853def getESELSeverity(esel):
854 """
855 Finds the severity type in an eSEL from the User Header section.
856 @param esel - the eSEL data
857 @return severity - e.g. 'Critical'
858 """
859
860 # everything but 1 and 2 are Critical
861 # '1': 'recovered',
862 # '2': 'predictive',
863 # '4': 'unrecoverable',
864 # '5': 'critical',
865 # '6': 'diagnostic',
866 # '7': 'symptom'
867 severities = {
868 '1': 'Informational',
869 '2': 'Warning'
870 }
871
872 try:
873 headerPosition = esel.index('55 48') # 'UH'
874 # The severity is the last byte in the 8 byte section (a byte is ' bb')
875 severity = esel[headerPosition:headerPosition+32].split(' ')[-1]
876 type = severity[0]
877 except ValueError:
878 print("Could not find severity value in UH section in eSEL")
879 type = 'x';
880
881 return severities.get(type, 'Critical')
882
883
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600884def sortSELs(events):
Justin Thalere412dc22018-01-12 16:28:24 -0600885 """
886 sorts the sels by timestamp, then log entry number
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600887
Justin Thalere412dc22018-01-12 16:28:24 -0600888 @param events: Dictionary containing events
889 @return: list containing a list of the ordered log entries, and dictionary of keys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600890 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600891 logNumList = []
892 timestampList = []
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600893 eventKeyDict = {}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600894 eventsWithTimestamp = {}
895 logNum2events = {}
896 for key in events:
897 if key == 'numAlerts': continue
898 if 'callout' in key: continue
899 timestamp = (events[key]['timestamp'])
900 if timestamp not in timestampList:
901 eventsWithTimestamp[timestamp] = [events[key]['logNum']]
902 else:
903 eventsWithTimestamp[timestamp].append(events[key]['logNum'])
904 #map logNumbers to the event dictionary keys
905 eventKeyDict[str(events[key]['logNum'])] = key
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600906
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600907 timestampList = list(eventsWithTimestamp.keys())
908 timestampList.sort()
909 for ts in timestampList:
910 if len(eventsWithTimestamp[ts]) > 1:
911 tmplist = eventsWithTimestamp[ts]
912 tmplist.sort()
913 logNumList = logNumList + tmplist
914 else:
915 logNumList = logNumList + eventsWithTimestamp[ts]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600916
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600917 return [logNumList, eventKeyDict]
918
Justin Thalere412dc22018-01-12 16:28:24 -0600919
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600920def parseAlerts(policyTable, selEntries, args):
Justin Thalere412dc22018-01-12 16:28:24 -0600921 """
922 parses alerts in the IBM CER format, using an IBM policy Table
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600923
Justin Thalere412dc22018-01-12 16:28:24 -0600924 @param policyTable: dictionary, the policy table entries
925 @param selEntries: dictionary, the alerts retrieved from the bmc
926 @return: A dictionary of the parsed entries, in chronological order
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600927 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600928 eventDict = {}
929 eventNum =""
930 count = 0
931 esel = ""
932 eselParts = {}
933 i2cdevice= ""
Matt Spinler02d0dff2018-08-29 13:19:25 -0500934 eselSeverity = None
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600935
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600936 'prepare and sort the event entries'
Justin Thaler667f87c2020-04-06 16:13:12 -0500937 sels = {}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600938 for key in selEntries:
Justin Thaler667f87c2020-04-06 16:13:12 -0500939 if '/xyz/openbmc_project/logging/entry/' not in key: continue
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600940 if 'callout' not in key:
Justin Thaler667f87c2020-04-06 16:13:12 -0500941 sels[key] = selEntries[key]
942 sels[key]['logNum'] = key.split('/')[-1]
943 sels[key]['timestamp'] = selEntries[key]['Timestamp']
944 sortedEntries = sortSELs(sels)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600945 logNumList = sortedEntries[0]
946 eventKeyDict = sortedEntries[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600947
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600948 for logNum in logNumList:
949 key = eventKeyDict[logNum]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600950 hasEsel=False
951 i2creadFail = False
952 if 'callout' in key:
953 continue
954 else:
955 messageID = str(selEntries[key]['Message'])
956 addDataPiece = selEntries[key]['AdditionalData']
957 calloutIndex = 0
958 calloutFound = False
959 for i in range(len(addDataPiece)):
960 if("CALLOUT_INVENTORY_PATH" in addDataPiece[i]):
961 calloutIndex = i
962 calloutFound = True
963 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
964 if("CALLOUT_DEVICE_PATH" in addDataPiece[i]):
965 i2creadFail = True
Matt Spinlerd178a472018-08-31 09:48:52 -0500966
967 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
968
969 # Fall back to "I2C"/"FSI" if dev path isn't in policy table
970 if (messageID + '||' + fruCallout) not in policyTable:
971 i2cdevice = str(addDataPiece[i]).strip().split('=')[1]
972 i2cdevice = '/'.join(i2cdevice.split('/')[-4:])
973 if 'fsi' in str(addDataPiece[calloutIndex]).split('=')[1]:
974 fruCallout = 'FSI'
975 else:
976 fruCallout = 'I2C'
Justin Thalere34c43a2018-05-25 19:37:55 -0500977 calloutFound = True
978 if("CALLOUT_GPIO_NUM" in addDataPiece[i]):
979 if not calloutFound:
980 fruCallout = 'GPIO'
981 calloutFound = True
982 if("CALLOUT_IIC_BUS" in addDataPiece[i]):
983 if not calloutFound:
984 fruCallout = "I2C"
985 calloutFound = True
986 if("CALLOUT_IPMI_SENSOR_NUM" in addDataPiece[i]):
987 if not calloutFound:
988 fruCallout = "IPMI"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600989 calloutFound = True
990 if("ESEL" in addDataPiece[i]):
991 esel = str(addDataPiece[i]).strip().split('=')[1]
Matt Spinler02d0dff2018-08-29 13:19:25 -0500992 eselSeverity = getESELSeverity(esel)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600993 if args.devdebug:
994 eselParts = parseESEL(args, esel)
995 hasEsel=True
996 if("GPU" in addDataPiece[i]):
997 fruCallout = '/xyz/openbmc_project/inventory/system/chassis/motherboard/gpu' + str(addDataPiece[i]).strip()[-1]
998 calloutFound = True
999 if("PROCEDURE" in addDataPiece[i]):
1000 fruCallout = str(hex(int(str(addDataPiece[i]).split('=')[1])))[2:]
1001 calloutFound = True
Justin Thalere412dc22018-01-12 16:28:24 -06001002 if("RAIL_NAME" in addDataPiece[i]):
1003 calloutFound=True
1004 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
1005 if("INPUT_NAME" in addDataPiece[i]):
1006 calloutFound=True
1007 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
1008 if("SENSOR_TYPE" in addDataPiece[i]):
1009 calloutFound=True
1010 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001011
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001012 if(calloutFound):
Justin Thaler667f87c2020-04-06 16:13:12 -05001013 if fruCallout.strip() != "":
Justin Thaler22b1bb52018-03-15 13:31:32 -05001014 policyKey = messageID +"||" + fruCallout
Matt Spinler02d0dff2018-08-29 13:19:25 -05001015
1016 # Also use the severity for hostboot errors
1017 if eselSeverity and messageID == 'org.open_power.Host.Error.Event':
1018 policyKey += '||' + eselSeverity
1019
1020 # if not in the table, fall back to the original key
1021 if policyKey not in policyTable:
1022 policyKey = policyKey.replace('||'+eselSeverity, '')
1023
Justin Thalere34c43a2018-05-25 19:37:55 -05001024 if policyKey not in policyTable:
1025 policyKey = messageID
Justin Thaler22b1bb52018-03-15 13:31:32 -05001026 else:
1027 policyKey = messageID
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001028 else:
1029 policyKey = messageID
1030 event = {}
1031 eventNum = str(count)
1032 if policyKey in policyTable:
1033 for pkey in policyTable[policyKey]:
1034 if(type(policyTable[policyKey][pkey])== bool):
1035 event[pkey] = boolToString(policyTable[policyKey][pkey])
1036 else:
1037 if (i2creadFail and pkey == 'Message'):
1038 event[pkey] = policyTable[policyKey][pkey] + ' ' +i2cdevice
1039 else:
1040 event[pkey] = policyTable[policyKey][pkey]
1041 event['timestamp'] = selEntries[key]['Timestamp']
1042 event['resolved'] = bool(selEntries[key]['Resolved'])
1043 if(hasEsel):
1044 if args.devdebug:
1045 event['eselParts'] = eselParts
1046 event['raweSEL'] = esel
1047 event['logNum'] = key.split('/')[-1]
1048 eventDict['event' + eventNum] = event
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001049
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001050 else:
1051 severity = str(selEntries[key]['Severity']).split('.')[-1]
1052 if severity == 'Error':
1053 severity = 'Critical'
1054 eventDict['event'+eventNum] = {}
1055 eventDict['event' + eventNum]['error'] = "error: Not found in policy table: " + policyKey
1056 eventDict['event' + eventNum]['timestamp'] = selEntries[key]['Timestamp']
1057 eventDict['event' + eventNum]['Severity'] = severity
1058 if(hasEsel):
1059 if args.devdebug:
1060 eventDict['event' +eventNum]['eselParts'] = eselParts
1061 eventDict['event' +eventNum]['raweSEL'] = esel
1062 eventDict['event' +eventNum]['logNum'] = key.split('/')[-1]
1063 eventDict['event' +eventNum]['resolved'] = bool(selEntries[key]['Resolved'])
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001064 count += 1
1065 return eventDict
1066
1067
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001068def selDisplay(events, args):
Justin Thalere412dc22018-01-12 16:28:24 -06001069 """
1070 displays alerts in human readable format
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001071
Justin Thalere412dc22018-01-12 16:28:24 -06001072 @param events: Dictionary containing events
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001073 @return:
1074 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001075 activeAlerts = []
1076 historyAlerts = []
1077 sortedEntries = sortSELs(events)
1078 logNumList = sortedEntries[0]
1079 eventKeyDict = sortedEntries[1]
1080 keylist = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message']
1081 if(args.devdebug):
1082 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message', 'eSEL contents']
1083 keylist.append('eSEL')
1084 else:
1085 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity', 'Message']
1086 for log in logNumList:
1087 selDict = {}
1088 alert = events[eventKeyDict[str(log)]]
1089 if('error' in alert):
1090 selDict['Entry'] = alert['logNum']
1091 selDict['ID'] = 'Unknown'
1092 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
1093 msg = alert['error']
1094 polMsg = msg.split("policy table:")[0]
1095 msg = msg.split("policy table:")[1]
1096 msgPieces = msg.split("||")
1097 err = msgPieces[0]
1098 if(err.find("org.open_power.")!=-1):
1099 err = err.split("org.open_power.")[1]
1100 elif(err.find("xyz.openbmc_project.")!=-1):
1101 err = err.split("xyz.openbmc_project.")[1]
1102 else:
1103 err = msgPieces[0]
1104 callout = ""
1105 if len(msgPieces) >1:
1106 callout = msgPieces[1]
1107 if(callout.find("/org/open_power/")!=-1):
1108 callout = callout.split("/org/open_power/")[1]
1109 elif(callout.find("/xyz/openbmc_project/")!=-1):
1110 callout = callout.split("/xyz/openbmc_project/")[1]
1111 else:
1112 callout = msgPieces[1]
1113 selDict['Message'] = polMsg +"policy table: "+ err + "||" + callout
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001114 selDict['Serviceable'] = 'Unknown'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001115 selDict['Severity'] = alert['Severity']
1116 else:
1117 selDict['Entry'] = alert['logNum']
1118 selDict['ID'] = alert['CommonEventID']
1119 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001120 selDict['Message'] = alert['Message']
1121 selDict['Serviceable'] = alert['Serviceable']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001122 selDict['Severity'] = alert['Severity']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001123
1124
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001125 eselOrder = ['refCode','signatureDescription', 'eselType', 'devdesc', 'calloutType', 'procedure']
1126 if ('eselParts' in alert and args.devdebug):
1127 eselOutput = ""
1128 for item in eselOrder:
1129 if item in alert['eselParts']:
1130 eselOutput = eselOutput + item + ": " + alert['eselParts'][item] + " | "
1131 selDict['eSEL'] = eselOutput
1132 else:
1133 if args.devdebug:
1134 selDict['eSEL'] = "None"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001135
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001136 if not alert['resolved']:
1137 activeAlerts.append(selDict)
1138 else:
1139 historyAlerts.append(selDict)
1140 mergedOutput = activeAlerts + historyAlerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001141 colWidth = setColWidth(keylist, len(colNames), dict(enumerate(mergedOutput)), colNames)
1142
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001143 output = ""
1144 if(len(activeAlerts)>0):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001145 row = ""
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001146 output +="----Active Alerts----\n"
1147 for i in range(0, len(colNames)):
1148 if i!=0: row =row + "| "
1149 row = row + colNames[i].ljust(colWidth[i])
1150 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001151
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001152 for i in range(0,len(activeAlerts)):
1153 row = ""
1154 for j in range(len(activeAlerts[i])):
1155 if (j != 0): row = row + "| "
1156 row = row + activeAlerts[i][keylist[j]].ljust(colWidth[j])
1157 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001158
1159 if(len(historyAlerts)>0):
1160 row = ""
1161 output+= "----Historical Alerts----\n"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001162 for i in range(len(colNames)):
1163 if i!=0: row =row + "| "
1164 row = row + colNames[i].ljust(colWidth[i])
1165 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001166
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001167 for i in range(0, len(historyAlerts)):
1168 row = ""
1169 for j in range(len(historyAlerts[i])):
1170 if (j != 0): row = row + "| "
1171 row = row + historyAlerts[i][keylist[j]].ljust(colWidth[j])
1172 output += row + "\n"
1173# print(events[eventKeyDict[str(log)]])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001174 return output
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001175
Justin Thalere412dc22018-01-12 16:28:24 -06001176
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001177def selPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001178 """
1179 prints out all bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001180
Justin Thalere412dc22018-01-12 16:28:24 -06001181 @param host: string, the hostname or IP address of the bmc
1182 @param args: contains additional arguments used by the fru sub command
1183 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001184 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1185 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001186 if(args.policyTableLoc is None):
1187 if os.path.exists('policyTable.json'):
1188 ptableLoc = "policyTable.json"
1189 elif os.path.exists('/opt/ibm/ras/lib/policyTable.json'):
1190 ptableLoc = '/opt/ibm/ras/lib/policyTable.json'
1191 else:
1192 ptableLoc = 'lib/policyTable.json'
1193 else:
1194 ptableLoc = args.policyTableLoc
1195 policyTable = loadPolicyTable(ptableLoc)
1196 rawselEntries = ""
1197 if(hasattr(args, 'fileloc') and args.fileloc is not None):
1198 if os.path.exists(args.fileloc):
1199 with open(args.fileloc, 'r') as selFile:
1200 selLines = selFile.readlines()
1201 rawselEntries = ''.join(selLines)
1202 else:
1203 print("Error: File not found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001204 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001205 else:
1206 rawselEntries = sel(host, args, session)
1207 loadFailed = False
1208 try:
1209 selEntries = json.loads(rawselEntries)
1210 except ValueError:
1211 loadFailed = True
1212 if loadFailed:
1213 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1214 #need to load json twice as original content was string escaped a second time
1215 selEntries = json.loads(json.loads(cleanSels))
1216 selEntries = selEntries['data']
Justin Thalere412dc22018-01-12 16:28:24 -06001217
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001218 if 'description' in selEntries:
1219 if(args.json):
1220 return("{\n\t\"numAlerts\": 0\n}")
1221 else:
1222 return("No log entries found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001223
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001224 else:
1225 if(len(policyTable)>0):
1226 events = parseAlerts(policyTable, selEntries, args)
1227 if(args.json):
1228 events["numAlerts"] = len(events)
1229 retValue = str(json.dumps(events, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
1230 return retValue
1231 elif(hasattr(args, 'fullSel')):
1232 return events
1233 else:
1234 #get log numbers to order event entries sequentially
1235 return selDisplay(events, args)
1236 else:
1237 if(args.json):
1238 return selEntries
1239 else:
1240 print("error: Policy Table not found.")
1241 return selEntries
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001242
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001243def selList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001244 """
1245 prints out all all bmc alerts, or only prints out the specified alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001246
Justin Thalere412dc22018-01-12 16:28:24 -06001247 @param host: string, the hostname or IP address of the bmc
1248 @param args: contains additional arguments used by the fru sub command
1249 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001250 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1251 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001252 return(sel(host, args, session))
1253
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001254
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001255def selClear(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001256 """
1257 clears all alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001258
Justin Thalere412dc22018-01-12 16:28:24 -06001259 @param host: string, the hostname or IP address of the bmc
1260 @param args: contains additional arguments used by the fru sub command
1261 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001262 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1263 """
Matt Spinler47b13e92019-01-04 14:58:53 -06001264 url="https://"+host+"/xyz/openbmc_project/logging/action/DeleteAll"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001265 data = "{\"data\": [] }"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001266
Justin Thalere412dc22018-01-12 16:28:24 -06001267 try:
Justin Thaler27197622019-01-23 14:42:11 -06001268 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001269 except(requests.exceptions.Timeout):
1270 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001271 if res.status_code == 200:
1272 return "The Alert Log has been cleared. Please allow a few minutes for the action to complete."
1273 else:
1274 print("Unable to clear the logs, trying to clear 1 at a time")
1275 sels = json.loads(sel(host, args, session))['data']
1276 for key in sels:
1277 if 'callout' not in key:
1278 logNum = key.split('/')[-1]
1279 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
1280 try:
Justin Thaler27197622019-01-23 14:42:11 -06001281 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001282 except(requests.exceptions.Timeout):
1283 return connectionErrHandler(args.json, "Timeout", None)
1284 sys.exit(1)
1285 except(requests.exceptions.ConnectionError) as err:
1286 return connectionErrHandler(args.json, "ConnectionError", err)
1287 sys.exit(1)
1288 return ('Sel clearing complete')
1289
1290def selSetResolved(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001291 """
1292 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001293
Justin Thalere412dc22018-01-12 16:28:24 -06001294 @param host: string, the hostname or IP address of the bmc
1295 @param args: contains additional arguments used by the fru sub command
1296 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001297 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1298 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001299 url="https://"+host+"/xyz/openbmc_project/logging/entry/" + str(args.selNum) + "/attr/Resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001300 data = "{\"data\": 1 }"
Justin Thalere412dc22018-01-12 16:28:24 -06001301 try:
Justin Thaler27197622019-01-23 14:42:11 -06001302 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001303 except(requests.exceptions.Timeout):
1304 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001305 if res.status_code == 200:
1306 return "Sel entry "+ str(args.selNum) +" is now set to resolved"
1307 else:
1308 return "Unable to set the alert to resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001309
Justin Thalere412dc22018-01-12 16:28:24 -06001310def selResolveAll(host, args, session):
1311 """
1312 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001313
Justin Thalere412dc22018-01-12 16:28:24 -06001314 @param host: string, the hostname or IP address of the bmc
1315 @param args: contains additional arguments used by the fru sub command
1316 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001317 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1318 """
Justin Thalere412dc22018-01-12 16:28:24 -06001319 rawselEntries = sel(host, args, session)
1320 loadFailed = False
1321 try:
1322 selEntries = json.loads(rawselEntries)
1323 except ValueError:
1324 loadFailed = True
1325 if loadFailed:
1326 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1327 #need to load json twice as original content was string escaped a second time
1328 selEntries = json.loads(json.loads(cleanSels))
1329 selEntries = selEntries['data']
1330
1331 if 'description' in selEntries:
1332 if(args.json):
1333 return("{\n\t\"selsResolved\": 0\n}")
1334 else:
1335 return("No log entries found")
1336 else:
1337 d = vars(args)
1338 successlist = []
1339 failedlist = []
1340 for key in selEntries:
1341 if 'callout' not in key:
1342 d['selNum'] = key.split('/')[-1]
1343 resolved = selSetResolved(host,args,session)
1344 if 'Sel entry' in resolved:
1345 successlist.append(d['selNum'])
1346 else:
1347 failedlist.append(d['selNum'])
1348 output = ""
1349 successlist.sort()
1350 failedlist.sort()
1351 if len(successlist)>0:
1352 output = "Successfully resolved: " +', '.join(successlist) +"\n"
1353 if len(failedlist)>0:
1354 output += "Failed to resolve: " + ', '.join(failedlist) + "\n"
1355 return output
1356
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001357def chassisPower(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001358 """
1359 called by the chassis function. Controls the power state of the chassis, or gets the status
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001360
Justin Thalere412dc22018-01-12 16:28:24 -06001361 @param host: string, the hostname or IP address of the bmc
1362 @param args: contains additional arguments used by the fru sub command
1363 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001364 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1365 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001366 if(args.powcmd == 'on'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001367 if checkFWactivation(host, args, session):
1368 return ("Chassis Power control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001369 print("Attempting to Power on...:")
1370 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001371 data = '{"data":"xyz.openbmc_project.State.Host.Transition.On"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001372 try:
Justin Thaler27197622019-01-23 14:42:11 -06001373 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001374 except(requests.exceptions.Timeout):
1375 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001376 return res.text
Justin Thalere412dc22018-01-12 16:28:24 -06001377 elif(args.powcmd == 'softoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001378 if checkFWactivation(host, args, session):
1379 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001380 print("Attempting to Power off gracefully...:")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001381 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001382 data = '{"data":"xyz.openbmc_project.State.Host.Transition.Off"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001383 try:
Justin Thaler27197622019-01-23 14:42:11 -06001384 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001385 except(requests.exceptions.Timeout):
1386 return(connectionErrHandler(args.json, "Timeout", None))
1387 return res.text
1388 elif(args.powcmd == 'hardoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001389 if checkFWactivation(host, args, session):
1390 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001391 print("Attempting to Power off immediately...:")
1392 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06001393 data = '{"data":"xyz.openbmc_project.State.Chassis.Transition.Off"}'
1394 try:
Justin Thaler27197622019-01-23 14:42:11 -06001395 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001396 except(requests.exceptions.Timeout):
1397 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001398 return res.text
1399 elif(args.powcmd == 'status'):
1400 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState"
Justin Thalere412dc22018-01-12 16:28:24 -06001401 try:
Justin Thaler27197622019-01-23 14:42:11 -06001402 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001403 except(requests.exceptions.Timeout):
1404 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001405 chassisState = json.loads(res.text)['data'].split('.')[-1]
1406 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/CurrentHostState"
Justin Thalere412dc22018-01-12 16:28:24 -06001407 try:
Justin Thaler27197622019-01-23 14:42:11 -06001408 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001409 except(requests.exceptions.Timeout):
1410 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001411 hostState = json.loads(res.text)['data'].split('.')[-1]
1412 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/CurrentBMCState"
Justin Thalere412dc22018-01-12 16:28:24 -06001413 try:
Justin Thaler27197622019-01-23 14:42:11 -06001414 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001415 except(requests.exceptions.Timeout):
1416 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001417 bmcState = json.loads(res.text)['data'].split('.')[-1]
1418 if(args.json):
1419 outDict = {"Chassis Power State" : chassisState, "Host Power State" : hostState, "BMC Power State":bmcState}
1420 return json.dumps(outDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
1421 else:
1422 return "Chassis Power State: " +chassisState + "\nHost Power State: " + hostState + "\nBMC Power State: " + bmcState
1423 else:
1424 return "Invalid chassis power command"
1425
Justin Thalere412dc22018-01-12 16:28:24 -06001426
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001427def chassisIdent(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001428 """
1429 called by the chassis function. Controls the identify led of the chassis. Sets or gets the state
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001430
Justin Thalere412dc22018-01-12 16:28:24 -06001431 @param host: string, the hostname or IP address of the bmc
1432 @param args: contains additional arguments used by the fru sub command
1433 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001434 @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 -06001435 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001436 if(args.identcmd == 'on'):
1437 print("Attempting to turn identify light on...:")
1438 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001439 data = '{"data":true}'
Justin Thalere412dc22018-01-12 16:28:24 -06001440 try:
Justin Thaler27197622019-01-23 14:42:11 -06001441 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001442 except(requests.exceptions.Timeout):
1443 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001444 return res.text
1445 elif(args.identcmd == 'off'):
1446 print("Attempting to turn identify light off...:")
1447 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001448 data = '{"data":false}'
Justin Thalere412dc22018-01-12 16:28:24 -06001449 try:
Justin Thaler27197622019-01-23 14:42:11 -06001450 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001451 except(requests.exceptions.Timeout):
1452 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001453 return res.text
1454 elif(args.identcmd == 'status'):
1455 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify"
Justin Thalere412dc22018-01-12 16:28:24 -06001456 try:
Justin Thaler27197622019-01-23 14:42:11 -06001457 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001458 except(requests.exceptions.Timeout):
1459 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001460 status = json.loads(res.text)['data']
1461 if(args.json):
1462 return status
1463 else:
1464 if status['Asserted'] == 0:
1465 return "Identify light is off"
1466 else:
1467 return "Identify light is blinking"
1468 else:
1469 return "Invalid chassis identify command"
1470
Justin Thalere412dc22018-01-12 16:28:24 -06001471
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001472def chassis(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001473 """
1474 controls the different chassis commands
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001475
Justin Thalere412dc22018-01-12 16:28:24 -06001476 @param host: string, the hostname or IP address of the bmc
1477 @param args: contains additional arguments used by the fru sub command
1478 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001479 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1480 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001481 if(hasattr(args, 'powcmd')):
1482 result = chassisPower(host,args,session)
1483 elif(hasattr(args, 'identcmd')):
1484 result = chassisIdent(host, args, session)
1485 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001486 return "This feature is not yet implemented"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001487 return result
Justin Thalere412dc22018-01-12 16:28:24 -06001488
Ravi Tejad8be0b42020-03-18 14:31:46 -05001489def dumpRetrieve(host, args, session):
1490 """
1491 Downloads dump of given dump type
1492
1493 @param host: string, the hostname or IP address of the bmc
1494 @param args: contains additional arguments used by the collectServiceData sub command
1495 @param session: the active session to use
1496 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1497 """
1498 dumpType = args.dumpType
1499 if (args.dumpType=="SystemDump"):
1500 dumpResp=systemDumpRetrieve(host,args,session)
1501 elif(args.dumpType=="bmc"):
1502 dumpResp=bmcDumpRetrieve(host,args,session)
1503 return dumpResp
1504
1505def dumpList(host, args, session):
1506 """
1507 Lists dump of the given dump type
1508
1509 @param host: string, the hostname or IP address of the bmc
1510 @param args: contains additional arguments used by the collectServiceData sub command
1511 @param session: the active session to use
1512 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1513 """
1514 if (args.dumpType=="SystemDump"):
1515 dumpResp=systemDumpList(host,args,session)
1516 elif(args.dumpType=="bmc"):
1517 dumpResp=bmcDumpList(host,args,session)
1518 return dumpResp
1519
1520def dumpDelete(host, args, session):
1521 """
1522 Deletes dump of the given dump type
1523
1524 @param host: string, the hostname or IP address of the bmc
1525 @param args: contains additional arguments used by the collectServiceData sub command
1526 @param session: the active session to use
1527 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1528 """
1529 if (args.dumpType=="SystemDump"):
1530 dumpResp=systemDumpDelete(host,args,session)
1531 elif(args.dumpType=="bmc"):
1532 dumpResp=bmcDumpDelete(host,args,session)
1533 return dumpResp
1534
1535def dumpDeleteAll(host, args, session):
1536 """
1537 Deletes all dumps of the given dump type
1538
1539 @param host: string, the hostname or IP address of the bmc
1540 @param args: contains additional arguments used by the collectServiceData sub command
1541 @param session: the active session to use
1542 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1543 """
1544 if (args.dumpType=="SystemDump"):
1545 dumpResp=systemDumpDeleteAll(host,args,session)
1546 elif(args.dumpType=="bmc"):
1547 dumpResp=bmcDumpDeleteAll(host,args,session)
1548 return dumpResp
1549
1550def dumpCreate(host, args, session):
1551 """
1552 Creates dump for the given dump type
1553
1554 @param host: string, the hostname or IP address of the bmc
1555 @param args: contains additional arguments used by the collectServiceData sub command
1556 @param session: the active session to use
1557 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1558 """
1559 if (args.dumpType=="SystemDump"):
1560 dumpResp=systemDumpCreate(host,args,session)
1561 elif(args.dumpType=="bmc"):
Justin Thaler0a3e1692020-04-07 19:10:40 -05001562 dumpResp=bmcDumpCreate(host,args,session)
Ravi Tejad8be0b42020-03-18 14:31:46 -05001563 return dumpResp
1564
1565
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001566def bmcDumpRetrieve(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001567 """
1568 Downloads a dump file from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001569
Justin Thalere412dc22018-01-12 16:28:24 -06001570 @param host: string, the hostname or IP address of the bmc
1571 @param args: contains additional arguments used by the collectServiceData sub command
1572 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001573 @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 -06001574 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001575 dumpNum = args.dumpNum
1576 if (args.dumpSaveLoc is not None):
1577 saveLoc = args.dumpSaveLoc
1578 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001579 saveLoc = tempfile.gettempdir()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001580 url ='https://'+host+'/download/dump/' + str(dumpNum)
1581 try:
Justin Thaler27197622019-01-23 14:42:11 -06001582 r = session.get(url, headers=jsonHeader, stream=True, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001583 if (args.dumpSaveLoc is not None):
1584 if os.path.exists(saveLoc):
1585 if saveLoc[-1] != os.path.sep:
1586 saveLoc = saveLoc + os.path.sep
1587 filename = saveLoc + host+'-dump' + str(dumpNum) + '.tar.xz'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001588
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001589 else:
1590 return 'Invalid save location specified'
1591 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001592 filename = tempfile.gettempdir()+os.sep + host+'-dump' + str(dumpNum) + '.tar.xz'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001593
1594 with open(filename, 'wb') as f:
1595 for chunk in r.iter_content(chunk_size =1024):
1596 if chunk:
1597 f.write(chunk)
1598 return 'Saved as ' + filename
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001599
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001600 except(requests.exceptions.Timeout):
1601 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001602
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001603 except(requests.exceptions.ConnectionError) as err:
1604 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001605
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001606def bmcDumpList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001607 """
1608 Lists the number of dump files on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001609
Justin Thalere412dc22018-01-12 16:28:24 -06001610 @param host: string, the hostname or IP address of the bmc
1611 @param args: contains additional arguments used by the collectServiceData sub command
1612 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001613 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1614 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001615 url ='https://'+host+'/xyz/openbmc_project/dump/list'
1616 try:
Justin Thaler27197622019-01-23 14:42:11 -06001617 r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3a5771b2019-01-23 14:31:52 -06001618 dumpList = r.json()
Justin Thaler3b3c6582020-04-07 19:17:36 -05001619 formattedList = []
1620 #remove items that aren't dump entries 'entry, internal, manager endpoints'
1621 if 'data' in dumpList:
1622 for entry in dumpList['data']:
1623 if 'entry' in entry:
1624 if entry.split('/')[-1].isnumeric():
1625 formattedList.append(entry)
1626 dumpList['data']= formattedList
Justin Thaler3a5771b2019-01-23 14:31:52 -06001627 return dumpList
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001628 except(requests.exceptions.Timeout):
1629 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001630
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001631 except(requests.exceptions.ConnectionError) as err:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001632 return connectionErrHandler(args.json, "ConnectionError", err)
1633
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001634def bmcDumpDelete(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001635 """
1636 Deletes BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001637
Justin Thalere412dc22018-01-12 16:28:24 -06001638 @param host: string, the hostname or IP address of the bmc
1639 @param args: contains additional arguments used by the collectServiceData sub command
1640 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001641 @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 -06001642 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001643 dumpList = []
1644 successList = []
1645 failedList = []
1646 if args.dumpNum is not None:
1647 if isinstance(args.dumpNum, list):
1648 dumpList = args.dumpNum
1649 else:
1650 dumpList.append(args.dumpNum)
1651 for dumpNum in dumpList:
1652 url ='https://'+host+'/xyz/openbmc_project/dump/entry/'+str(dumpNum)+'/action/Delete'
1653 try:
Justin Thaler27197622019-01-23 14:42:11 -06001654 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001655 if r.status_code == 200:
1656 successList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001657 else:
1658 failedList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001659 except(requests.exceptions.Timeout):
1660 return connectionErrHandler(args.json, "Timeout", None)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001661 except(requests.exceptions.ConnectionError) as err:
1662 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001663 output = "Successfully deleted dumps: " + ', '.join(successList)
1664 if(len(failedList)>0):
1665 output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
1666 return output
1667 else:
1668 return 'You must specify an entry number to delete'
1669
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001670def bmcDumpDeleteAll(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001671 """
1672 Deletes All BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001673
Justin Thalere412dc22018-01-12 16:28:24 -06001674 @param host: string, the hostname or IP address of the bmc
1675 @param args: contains additional arguments used by the collectServiceData sub command
1676 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001677 @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 -06001678 """
1679 dumpResp = bmcDumpList(host, args, session)
1680 if 'FQPSPIN0000M' in dumpResp or 'FQPSPIN0001M'in dumpResp:
1681 return dumpResp
Justin Thaler3a5771b2019-01-23 14:31:52 -06001682 dumpList = dumpResp['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001683 d = vars(args)
1684 dumpNums = []
1685 for dump in dumpList:
Alvin Wang28bd09d2019-10-28 13:23:58 +08001686 dumpNum = dump.strip().split('/')[-1]
1687 if dumpNum.isdigit():
1688 dumpNums.append(int(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001689 d['dumpNum'] = dumpNums
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001690
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001691 return bmcDumpDelete(host, args, session)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001692
Justin Thalere412dc22018-01-12 16:28:24 -06001693
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001694def bmcDumpCreate(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001695 """
1696 Creates a bmc dump file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001697
Justin Thalere412dc22018-01-12 16:28:24 -06001698 @param host: string, the hostname or IP address of the bmc
1699 @param args: contains additional arguments used by the collectServiceData sub command
1700 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001701 @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 -06001702 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001703 url = 'https://'+host+'/xyz/openbmc_project/dump/action/CreateDump'
1704 try:
Justin Thaler27197622019-01-23 14:42:11 -06001705 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Matt Spinlereae05b02019-01-24 12:59:34 -06001706 if(r.status_code == 200 and not args.json):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001707 return ('Dump successfully created')
Justin Thaler3a5771b2019-01-23 14:31:52 -06001708 elif(args.json):
1709 return r.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001710 else:
1711 return ('Failed to create dump')
1712 except(requests.exceptions.Timeout):
1713 return connectionErrHandler(args.json, "Timeout", None)
1714 except(requests.exceptions.ConnectionError) as err:
1715 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001716
Ravi Tejad8be0b42020-03-18 14:31:46 -05001717def systemDumpRetrieve(host, args, session):
1718 """
1719 Downloads system dump
1720
1721 @param host: string, the hostname or IP address of the bmc
1722 @param args: contains additional arguments used by the collectServiceData sub command
1723 @param session: the active session to use
1724 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1725 """
1726 NBDSetup(host,args,session)
1727 pipe = NBDPipe()
1728 pipe.openHTTPSocket(args)
1729 pipe.openTCPSocket()
1730 pipe.waitformessage()
1731
1732def systemDumpList(host, args, session):
1733 """
1734 Lists system dumps
1735
1736 @param host: string, the hostname or IP address of the bmc
1737 @param args: contains additional arguments used by the collectServiceData sub command
1738 @param session: the active session to use
1739 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1740 """
1741 print("in systemDumpList")
1742 url = "https://"+host+"/redfish/v1/Systems/system/LogServices/"+args.dumpType+"/Entries"
1743 try:
1744 r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
1745 dumpList = r.json()
1746 return dumpList
1747 except(requests.exceptions.Timeout):
1748 return connectionErrHandler(args.json, "Timeout", None)
1749
1750 except(requests.exceptions.ConnectionError) as err:
1751 return connectionErrHandler(args.json, "ConnectionError", err)
1752
1753
1754def systemDumpDelete(host, args, session):
1755 """
1756 Deletes system dump
1757
1758 @param host: string, the hostname or IP address of the bmc
1759 @param args: contains additional arguments used by the collectServiceData sub command
1760 @param session: the active session to use
1761 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1762 """
1763 dumpList = []
1764 successList = []
1765 failedList = []
1766 if args.dumpNum is not None:
1767 if isinstance(args.dumpNum, list):
1768 dumpList = args.dumpNum
1769 else:
1770 dumpList.append(args.dumpNum)
1771 for dumpNum in dumpList:
1772 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/'+args.dumpType+'/Entries/'+ str(dumpNum)
1773 try:
1774 r = session.delete(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1775 if r.status_code == 200:
1776 successList.append(str(dumpNum))
1777 else:
1778 failedList.append(str(dumpNum))
1779 except(requests.exceptions.Timeout):
1780 return connectionErrHandler(args.json, "Timeout", None)
1781 except(requests.exceptions.ConnectionError) as err:
1782 return connectionErrHandler(args.json, "ConnectionError", err)
1783 output = "Successfully deleted dumps: " + ', '.join(successList)
1784 if(len(failedList)>0):
1785 output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
1786 return output
1787 else:
1788 return 'You must specify an entry number to delete'
1789
1790def systemDumpDeleteAll(host, args, session):
1791 """
1792 Deletes All system dumps
1793
1794 @param host: string, the hostname or IP address of the bmc
1795 @param args: contains additional arguments used by the collectServiceData sub command
1796 @param session: the active session to use
1797 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1798 """
1799 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/'+args.dumpType+'/Actions/LogService.ClearLog'
1800 try:
1801 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1802 if(r.status_code == 200 and not args.json):
1803 return ('Dumps successfully cleared')
1804 elif(args.json):
1805 return r.json()
1806 else:
1807 return ('Failed to clear dumps')
1808 except(requests.exceptions.Timeout):
1809 return connectionErrHandler(args.json, "Timeout", None)
1810 except(requests.exceptions.ConnectionError) as err:
1811 return connectionErrHandler(args.json, "ConnectionError", err)
1812
1813def systemDumpCreate(host, args, session):
1814 """
1815 Creates a system dump
1816
1817 @param host: string, the hostname or IP address of the bmc
1818 @param args: contains additional arguments used by the collectServiceData sub command
1819 @param session: the active session to use
1820 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1821 """
1822 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/'+args.dumpType+'/Actions/Oem/Openbmc/LogService.CreateLog'
1823 try:
1824 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1825 if(r.status_code == 200 and not args.json):
1826 return ('Dump successfully created')
1827 elif(args.json):
1828 return r.json()
1829 else:
1830 return ('Failed to create dump')
1831 except(requests.exceptions.Timeout):
1832 return connectionErrHandler(args.json, "Timeout", None)
1833 except(requests.exceptions.ConnectionError) as err:
1834 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001835
Justin Thaler666cf342019-01-23 14:44:27 -06001836def csdDumpInitiate(host, args, session):
1837 """
1838 Starts the process of getting the current list of dumps then initiates the creation of one.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001839
Justin Thaler666cf342019-01-23 14:44:27 -06001840 @param host: string, the hostname or IP address of the bmc
1841 @param args: contains additional arguments used by the collectServiceData sub command
1842 @param session: the active session to use
1843 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1844 """
1845 errorInfo = ""
1846 dumpcount = 0
1847 try:
1848 d = vars(args)
1849 d['json'] = True
1850 except Exception as e:
1851 errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
1852
1853 try:
1854 for i in range(3):
1855 dumpInfo = bmcDumpList(host, args, session)
1856 if 'data' in dumpInfo:
1857 dumpcount = len(dumpInfo['data'])
1858 break
1859 else:
1860 errorInfo+= "Dump List Message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n"
1861 except Exception as e:
1862 errorInfo+= "Failed to collect the list of dumps.\nException: {eInfo}\n".format(eInfo=e)
1863
1864 #Create a user initiated dump
1865 try:
1866 for i in range(3):
1867 dumpcreated = bmcDumpCreate(host, args, session)
1868 if 'message' in dumpcreated:
1869 if 'ok' in dumpcreated['message'].lower():
1870 break
1871 else:
1872 errorInfo+= "Dump create message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n"
1873 else:
1874 errorInfo+= "Dump create message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n"
1875 except Exception as e:
1876 errorInfo+= "Dump create exception encountered: {eInfo}\n".format(eInfo=e)
1877
1878 output = {}
1879 output['errors'] = errorInfo
1880 output['dumpcount'] = dumpcount
1881 return output
1882
1883def csdInventory(host, args,session, fileDir):
1884 """
1885 Collects the BMC inventory, retrying if necessary
1886
1887 @param host: string, the hostname or IP address of the bmc
1888 @param args: contains additional arguments used by the collectServiceData sub command
1889 @param session: the active session to use
1890 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1891 @param fileDir: string representation of the path to use for putting files created
1892 """
1893 errorInfo = "===========Inventory =============\n"
1894 output={}
1895 inventoryCollected = False
1896 try:
1897 for i in range(3):
1898 frulist = fruPrint(host, args, session)
1899 if 'Hardware' in frulist:
1900 inventoryCollected = True
1901 break
1902 else:
1903 errorInfo += json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1904 except Exception as e:
1905 errorInfo += "Inventory collection exception: {eInfo}\n".format(eInfo=e)
1906 if inventoryCollected:
1907 try:
1908 with open(fileDir +os.sep+'inventory.txt', 'w') as f:
1909 f.write(json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
1910 print("Inventory collected and stored in " + fileDir + os.sep + "inventory.txt")
1911 output['fileLoc'] = fileDir+os.sep+'inventory.txt'
1912 except Exception as e:
1913 print("Failed to write inventory to file.")
1914 errorInfo += "Error writing inventory to the file. Exception: {eInfo}\n".format(eInfo=e)
1915
1916 output['errors'] = errorInfo
1917
1918 return output
1919
1920def csdSensors(host, args,session, fileDir):
1921 """
1922 Collects the BMC sensor readings, retrying if necessary
1923
1924 @param host: string, the hostname or IP address of the bmc
1925 @param args: contains additional arguments used by the collectServiceData sub command
1926 @param session: the active session to use
1927 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1928 @param fileDir: string representation of the path to use for putting files created
1929 """
1930 errorInfo = "===========Sensors =============\n"
1931 sensorsCollected = False
1932 output={}
1933 try:
1934 d = vars(args)
1935 d['json'] = False
1936 except Exception as e:
1937 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
1938
1939 try:
1940 for i in range(3):
1941 sensorReadings = sensor(host, args, session)
1942 if 'OCC0' in sensorReadings:
1943 sensorsCollected = True
1944 break
1945 else:
1946 errorInfo += sensorReadings
1947 except Exception as e:
1948 errorInfo += "Sensor reading collection exception: {eInfo}\n".format(eInfo=e)
1949 if sensorsCollected:
1950 try:
1951 with open(fileDir +os.sep+'sensorReadings.txt', 'w') as f:
1952 f.write(sensorReadings)
1953 print("Sensor readings collected and stored in " + fileDir + os.sep+ "sensorReadings.txt")
1954 output['fileLoc'] = fileDir+os.sep+'sensorReadings.txt'
1955 except Exception as e:
1956 print("Failed to write sensor readings to file system.")
1957 errorInfo += "Error writing sensor readings to the file. Exception: {eInfo}\n".format(eInfo=e)
1958
1959 output['errors'] = errorInfo
1960 return output
1961
1962def csdLEDs(host,args, session, fileDir):
1963 """
1964 Collects the BMC LED status, retrying if necessary
1965
1966 @param host: string, the hostname or IP address of the bmc
1967 @param args: contains additional arguments used by the collectServiceData sub command
1968 @param session: the active session to use
1969 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1970 @param fileDir: string representation of the path to use for putting files created
1971 """
1972 errorInfo = "===========LEDs =============\n"
1973 ledsCollected = False
1974 output={}
1975 try:
1976 d = vars(args)
1977 d['json'] = True
1978 except Exception as e:
1979 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
1980 try:
1981 url="https://"+host+"/xyz/openbmc_project/led/enumerate"
1982 httpHeader = {'Content-Type':'application/json'}
1983 for i in range(3):
1984 try:
1985 ledRes = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
1986 if ledRes.status_code == 200:
1987 ledsCollected = True
1988 leds = ledRes.json()['data']
1989 break
1990 else:
1991 errorInfo += ledRes.text
1992 except(requests.exceptions.Timeout):
1993 errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1994 except(requests.exceptions.ConnectionError) as err:
1995 errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1996 except Exception as e:
1997 errorInfo += "LED status collection exception: {eInfo}\n".format(eInfo=e)
1998
1999 if ledsCollected:
2000 try:
2001 with open(fileDir +os.sep+'ledStatus.txt', 'w') as f:
2002 f.write(json.dumps(leds, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
2003 print("LED status collected and stored in " + fileDir + os.sep+ "ledStatus.txt")
2004 output['fileLoc'] = fileDir+os.sep+'ledStatus.txt'
2005 except Exception as e:
2006 print("Failed to write LED status to file system.")
2007 errorInfo += "Error writing LED status to the file. Exception: {eInfo}\n".format(eInfo=e)
2008
2009 output['errors'] = errorInfo
2010 return output
2011
2012def csdSelShortList(host, args, session, fileDir):
2013 """
2014 Collects the BMC log entries, retrying if necessary
2015
2016 @param host: string, the hostname or IP address of the bmc
2017 @param args: contains additional arguments used by the collectServiceData sub command
2018 @param session: the active session to use
2019 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2020 @param fileDir: string representation of the path to use for putting files created
2021 """
2022 errorInfo = "===========SEL Short List =============\n"
2023 selsCollected = False
2024 output={}
2025 try:
2026 d = vars(args)
2027 d['json'] = False
2028 except Exception as e:
2029 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
2030
2031 try:
2032 for i in range(3):
2033 sels = selPrint(host,args,session)
2034 if '----Active Alerts----' in sels or 'No log entries found' in sels or '----Historical Alerts----' in sels:
2035 selsCollected = True
2036 break
2037 else:
2038 errorInfo += sels + '\n'
2039 except Exception as e:
2040 errorInfo += "SEL short list collection exception: {eInfo}\n".format(eInfo=e)
2041
2042 if selsCollected:
2043 try:
2044 with open(fileDir +os.sep+'SELshortlist.txt', 'w') as f:
2045 f.write(sels)
2046 print("SEL short list collected and stored in " + fileDir + os.sep+ "SELshortlist.txt")
2047 output['fileLoc'] = fileDir+os.sep+'SELshortlist.txt'
2048 except Exception as e:
2049 print("Failed to write SEL short list to file system.")
2050 errorInfo += "Error writing SEL short list to the file. Exception: {eInfo}\n".format(eInfo=e)
2051
2052 output['errors'] = errorInfo
2053 return output
2054
2055def csdParsedSels(host, args, session, fileDir):
2056 """
2057 Collects the BMC log entries, retrying if necessary
2058
2059 @param host: string, the hostname or IP address of the bmc
2060 @param args: contains additional arguments used by the collectServiceData sub command
2061 @param session: the active session to use
2062 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2063 @param fileDir: string representation of the path to use for putting files created
2064 """
2065 errorInfo = "===========SEL Parsed List =============\n"
2066 selsCollected = False
2067 output={}
2068 try:
2069 d = vars(args)
2070 d['json'] = True
2071 d['fullEsel'] = True
2072 except Exception as e:
2073 errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
2074
2075 try:
2076 for i in range(3):
2077 parsedfullsels = json.loads(selPrint(host,args,session))
2078 if 'numAlerts' in parsedfullsels:
2079 selsCollected = True
2080 break
2081 else:
2082 errorInfo += parsedfullsels + '\n'
2083 except Exception as e:
2084 errorInfo += "Parsed full SELs collection exception: {eInfo}\n".format(eInfo=e)
2085
2086 if selsCollected:
2087 try:
2088 sortedSELs = sortSELs(parsedfullsels)
2089 with open(fileDir +os.sep+'parsedSELs.txt', 'w') as f:
2090 for log in sortedSELs[0]:
2091 esel = ""
2092 parsedfullsels[sortedSELs[1][str(log)]]['timestamp'] = datetime.datetime.fromtimestamp(int(parsedfullsels[sortedSELs[1][str(log)]]['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
2093 if ('raweSEL' in parsedfullsels[sortedSELs[1][str(log)]] and args.devdebug):
2094 esel = parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
2095 del parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
2096 f.write(json.dumps(parsedfullsels[sortedSELs[1][str(log)]],sort_keys=True, indent=4, separators=(',', ': ')))
2097 if(args.devdebug and esel != ""):
2098 f.write(parseESEL(args, esel))
2099 print("Parsed SELs collected and stored in " + fileDir + os.sep+ "parsedSELs.txt")
2100 output['fileLoc'] = fileDir+os.sep+'parsedSELs.txt'
2101 except Exception as e:
2102 print("Failed to write fully parsed SELs to file system.")
2103 errorInfo += "Error writing fully parsed SELs to the file. Exception: {eInfo}\n".format(eInfo=e)
2104
2105 output['errors'] = errorInfo
2106 return output
2107
2108def csdFullEnumeration(host, args, session, fileDir):
2109 """
2110 Collects a full enumeration of /xyz/openbmc_project/, retrying if necessary
2111
2112 @param host: string, the hostname or IP address of the bmc
2113 @param args: contains additional arguments used by the collectServiceData sub command
2114 @param session: the active session to use
2115 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2116 @param fileDir: string representation of the path to use for putting files created
2117 """
2118 errorInfo = "===========BMC Full Enumeration =============\n"
2119 bmcFullCollected = False
2120 output={}
2121 try:
2122 d = vars(args)
2123 d['json'] = True
2124 except Exception as e:
2125 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
2126 try:
2127 print("Attempting to get a full BMC enumeration")
2128 url="https://"+host+"/xyz/openbmc_project/enumerate"
2129 httpHeader = {'Content-Type':'application/json'}
2130 for i in range(3):
2131 try:
2132 bmcRes = session.get(url, headers=jsonHeader, verify=False, timeout=180)
2133 if bmcRes.status_code == 200:
2134 bmcFullCollected = True
2135 fullEnumeration = bmcRes.json()
2136 break
2137 else:
2138 errorInfo += bmcRes.text
2139 except(requests.exceptions.Timeout):
2140 errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
2141 except(requests.exceptions.ConnectionError) as err:
2142 errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
2143 except Exception as e:
2144 errorInfo += "RAW BMC data collection exception: {eInfo}\n".format(eInfo=e)
2145
2146 if bmcFullCollected:
2147 try:
2148 with open(fileDir +os.sep+'bmcFullRaw.txt', 'w') as f:
2149 f.write(json.dumps(fullEnumeration, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
2150 print("RAW BMC data collected and saved into " + fileDir + os.sep+ "bmcFullRaw.txt")
2151 output['fileLoc'] = fileDir+os.sep+'bmcFullRaw.txt'
2152 except Exception as e:
2153 print("Failed to write RAW BMC data to file system.")
2154 errorInfo += "Error writing RAW BMC data collection to the file. Exception: {eInfo}\n".format(eInfo=e)
2155
2156 output['errors'] = errorInfo
2157 return output
2158
2159def csdCollectAllDumps(host, args, session, fileDir):
2160 """
2161 Collects all of the bmc dump files and stores them in fileDir
2162
2163 @param host: string, the hostname or IP address of the bmc
2164 @param args: contains additional arguments used by the collectServiceData sub command
2165 @param session: the active session to use
2166 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2167 @param fileDir: string representation of the path to use for putting files created
2168 """
2169
2170 errorInfo = "===========BMC Dump Collection =============\n"
2171 dumpListCollected = False
2172 output={}
2173 dumpList = {}
2174 try:
2175 d = vars(args)
2176 d['json'] = True
2177 d['dumpSaveLoc'] = fileDir
2178 except Exception as e:
2179 errorInfo += "Failed to set the json flag to True, or failed to set the dumpSave Location \n Exception: {eInfo}\n".format(eInfo=e)
2180
2181 print('Collecting bmc dump files')
2182
2183 try:
2184 for i in range(3):
2185 dumpResp = bmcDumpList(host, args, session)
2186 if 'message' in dumpResp:
2187 if 'ok' in dumpResp['message'].lower():
2188 dumpList = dumpResp['data']
2189 dumpListCollected = True
2190 break
2191 else:
2192 errorInfo += "Status was not OK when retrieving the list of dumps available. \n Response: \n{resp}\n".format(resp=dumpResp)
2193 else:
2194 errorInfo += "Invalid response received from the BMC while retrieving the list of dumps available.\n {resp}\n".format(resp=dumpResp)
2195 except Exception as e:
2196 errorInfo += "BMC dump list exception: {eInfo}\n".format(eInfo=e)
2197
2198 if dumpListCollected:
2199 output['fileList'] = []
2200 for dump in dumpList:
2201 try:
2202 if '/xyz/openbmc_project/dump/internal/manager' not in dump:
2203 d['dumpNum'] = int(dump.strip().split('/')[-1])
2204 print('retrieving dump file ' + str(d['dumpNum']))
2205 filename = bmcDumpRetrieve(host, args, session).split('Saved as ')[-1]
2206 output['fileList'].append(filename)
2207 except Exception as e:
2208 print("Unable to collect dump: {dumpInfo}".format(dumpInfo=dump))
2209 errorInfo += "Exception collecting a bmc dump {dumpInfo}\n {eInfo}\n".format(dumpInfo=dump, eInfo=e)
2210 output['errors'] = errorInfo
2211 return output
Justin Thalere412dc22018-01-12 16:28:24 -06002212
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002213def collectServiceData(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002214 """
2215 Collects all data needed for service from the BMC
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002216
Justin Thalere412dc22018-01-12 16:28:24 -06002217 @param host: string, the hostname or IP address of the bmc
2218 @param args: contains additional arguments used by the collectServiceData sub command
2219 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002220 @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 -06002221 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002222
Justin Thaler22b1bb52018-03-15 13:31:32 -05002223 global toolVersion
Justin Thaler666cf342019-01-23 14:44:27 -06002224 filelist = []
2225 errorInfo = ""
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002226
Justin Thaler666cf342019-01-23 14:44:27 -06002227 #get current number of bmc dumps and create a new bmc dump
2228 dumpInitdata = csdDumpInitiate(host, args, session)
2229 dumpcount = dumpInitdata['dumpcount']
2230 errorInfo += dumpInitdata['errors']
2231 #create the directory to put files
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002232 try:
2233 args.silent = True
Justin Thalercf1deae2018-05-25 19:35:21 -05002234 myDir = tempfile.gettempdir()+os.sep + host + "--" + datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%S")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002235 os.makedirs(myDir)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002236
Justin Thaler666cf342019-01-23 14:44:27 -06002237 except Exception as e:
2238 print('Unable to create the temporary directory for data collection. Ensure sufficient privileges to create temporary directory. Aborting.')
2239 return("Python exception: {eInfo}".format(eInfo = e))
2240
2241 #Collect Inventory
2242 inventoryData = csdInventory(host, args, session, myDir)
2243 if 'fileLoc' in inventoryData:
2244 filelist.append(inventoryData['fileLoc'])
2245 errorInfo += inventoryData['errors']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002246 #Read all the sensor and OCC status
Justin Thaler666cf342019-01-23 14:44:27 -06002247 sensorData = csdSensors(host,args,session,myDir)
2248 if 'fileLoc' in sensorData:
2249 filelist.append(sensorData['fileLoc'])
2250 errorInfo += sensorData['errors']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002251 #Collect all of the LEDs status
Justin Thaler666cf342019-01-23 14:44:27 -06002252 ledStatus = csdLEDs(host, args, session, myDir)
2253 if 'fileLoc' in ledStatus:
2254 filelist.append(ledStatus['fileLoc'])
2255 errorInfo += ledStatus['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002256
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002257 #Collect the bmc logs
Justin Thaler666cf342019-01-23 14:44:27 -06002258 selShort = csdSelShortList(host, args, session, myDir)
2259 if 'fileLoc' in selShort:
2260 filelist.append(selShort['fileLoc'])
2261 errorInfo += selShort['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002262
Justin Thaler666cf342019-01-23 14:44:27 -06002263 parsedSELs = csdParsedSels(host, args, session, myDir)
2264 if 'fileLoc' in parsedSELs:
2265 filelist.append(parsedSELs['fileLoc'])
2266 errorInfo += parsedSELs['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002267
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002268 #collect RAW bmc enumeration
Justin Thaler666cf342019-01-23 14:44:27 -06002269 bmcRaw = csdFullEnumeration(host, args, session, myDir)
2270 if 'fileLoc' in bmcRaw:
2271 filelist.append(bmcRaw['fileLoc'])
2272 errorInfo += bmcRaw['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002273
Justin Thaler666cf342019-01-23 14:44:27 -06002274 #wait for new dump to finish being created
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002275 waitingForNewDump = True
2276 count = 0;
Justin Thaler666cf342019-01-23 14:44:27 -06002277 print("Waiting for new BMC dump to finish being created.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002278 while(waitingForNewDump):
Justin Thaler666cf342019-01-23 14:44:27 -06002279 dumpList = bmcDumpList(host, args, session)['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002280 if len(dumpList) > dumpcount:
2281 waitingForNewDump = False
2282 break;
2283 elif(count>30):
2284 print("Timed out waiting for bmc to make a new dump file. Dump space may be full.")
2285 break;
2286 else:
2287 time.sleep(2)
2288 count += 1
Justin Thaler666cf342019-01-23 14:44:27 -06002289
2290 #collect all of the dump files
2291 getBMCDumps = csdCollectAllDumps(host, args, session, myDir)
2292 if 'fileList' in getBMCDumps:
2293 filelist+= getBMCDumps['fileList']
2294 errorInfo += getBMCDumps['errors']
2295
2296 #write the runtime errors to a file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002297 try:
Justin Thaler666cf342019-01-23 14:44:27 -06002298 with open(myDir +os.sep+'openbmctoolRuntimeErrors.txt', 'w') as f:
2299 f.write(errorInfo)
2300 print("OpenBMC tool runtime errors collected and stored in " + myDir + os.sep+ "openbmctoolRuntimeErrors.txt")
2301 filelist.append(myDir+os.sep+'openbmctoolRuntimeErrors.txt')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002302 except Exception as e:
Justin Thaler666cf342019-01-23 14:44:27 -06002303 print("Failed to write OpenBMC tool runtime errors to file system.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002304
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002305 #create the zip file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002306 try:
Justin Thalercf1deae2018-05-25 19:35:21 -05002307 filename = myDir.split(tempfile.gettempdir()+os.sep)[-1] + "_" + toolVersion + '_openbmc.zip'
Justin Thaler666cf342019-01-23 14:44:27 -06002308 zf = zipfile.ZipFile(myDir+os.sep + filename, 'w')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002309 for myfile in filelist:
2310 zf.write(myfile, os.path.basename(myfile))
2311 zf.close()
Justin Thaler666cf342019-01-23 14:44:27 -06002312 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 -06002313 except Exception as e:
2314 print("Failed to create zip file with collected information")
Justin Thaler666cf342019-01-23 14:44:27 -06002315 return "data collection finished"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002316
Justin Thalere412dc22018-01-12 16:28:24 -06002317
2318def healthCheck(host, args, session):
2319 """
2320 runs a health check on the platform
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002321
Justin Thalere412dc22018-01-12 16:28:24 -06002322 @param host: string, the hostname or IP address of the bmc
2323 @param args: contains additional arguments used by the bmc sub command
2324 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002325 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2326 """
Justin Thalere412dc22018-01-12 16:28:24 -06002327 #check fru status and get as json to easily work through
2328 d = vars(args)
2329 useJson = d['json']
2330 d['json'] = True
2331 d['verbose']= False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002332
Justin Thalere412dc22018-01-12 16:28:24 -06002333 frus = json.loads(fruStatus(host, args, session))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002334
Justin Thalere412dc22018-01-12 16:28:24 -06002335 hwStatus= "OK"
2336 performanceStatus = "OK"
2337 for key in frus:
2338 if frus[key]["Functional"] == "No" and frus[key]["Present"] == "Yes":
2339 hwStatus= "Degraded"
Justin Thalerfb9c81c2018-07-16 11:14:37 -05002340 if("power_supply" in key or "powersupply" in key):
2341 gpuCount =0
2342 for comp in frus:
Justin Thalere412dc22018-01-12 16:28:24 -06002343 if "gv100card" in comp:
2344 gpuCount +=1
2345 if gpuCount > 4:
2346 hwStatus = "Critical"
2347 performanceStatus="Degraded"
2348 break;
2349 elif("fan" in key):
2350 hwStatus = "Degraded"
2351 else:
2352 performanceStatus = "Degraded"
2353 if useJson:
2354 output = {"Hardware Status": hwStatus, "Performance": performanceStatus}
2355 output = json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
2356 else:
2357 output = ("Hardware Status: " + hwStatus +
2358 "\nPerformance: " +performanceStatus )
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002359
2360
Justin Thalere412dc22018-01-12 16:28:24 -06002361 #SW407886: Clear the duplicate entries
2362 #collect the dups
2363 d['devdebug'] = False
2364 sels = json.loads(selPrint(host, args, session))
2365 logNums2Clr = []
2366 oldestLogNum={"logNum": "bogus" ,"key" : ""}
2367 count = 0
2368 if sels['numAlerts'] > 0:
2369 for key in sels:
2370 if "numAlerts" in key:
2371 continue
2372 try:
2373 if "slave@00:00/00:00:00:06/sbefifo1-dev0/occ1-dev0" in sels[key]['Message']:
2374 count += 1
2375 if count > 1:
2376 #preserve first occurrence
2377 if sels[key]['timestamp'] < sels[oldestLogNum['key']]['timestamp']:
2378 oldestLogNum['key']=key
2379 oldestLogNum['logNum'] = sels[key]['logNum']
2380 else:
2381 oldestLogNum['key']=key
2382 oldestLogNum['logNum'] = sels[key]['logNum']
2383 logNums2Clr.append(sels[key]['logNum'])
2384 except KeyError:
2385 continue
2386 if(count >0):
2387 logNums2Clr.remove(oldestLogNum['logNum'])
2388 #delete the dups
2389 if count >1:
Justin Thalere412dc22018-01-12 16:28:24 -06002390 data = "{\"data\": [] }"
2391 for logNum in logNums2Clr:
2392 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
2393 try:
Justin Thaler27197622019-01-23 14:42:11 -06002394 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002395 except(requests.exceptions.Timeout):
2396 deleteFailed = True
2397 except(requests.exceptions.ConnectionError) as err:
2398 deleteFailed = True
2399 #End of defect resolve code
2400 d['json'] = useJson
2401 return output
2402
2403
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002404
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002405def bmc(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002406 """
2407 handles various bmc level commands, currently bmc rebooting
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002408
Justin Thalere412dc22018-01-12 16:28:24 -06002409 @param host: string, the hostname or IP address of the bmc
2410 @param args: contains additional arguments used by the bmc sub command
2411 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002412 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2413 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002414 if(args.type is not None):
2415 return bmcReset(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06002416 if(args.info):
2417 return "Not implemented at this time"
2418
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002419
Justin Thalere412dc22018-01-12 16:28:24 -06002420
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002421def bmcReset(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002422 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002423 controls resetting the bmc. warm reset reboots the bmc, cold reset removes the configuration and reboots.
2424
Justin Thalere412dc22018-01-12 16:28:24 -06002425 @param host: string, the hostname or IP address of the bmc
2426 @param args: contains additional arguments used by the bmcReset sub command
2427 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002428 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2429 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002430 if checkFWactivation(host, args, session):
2431 return ("BMC reset control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002432 if(args.type == "warm"):
2433 print("\nAttempting to reboot the BMC...:")
2434 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06002435 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06002436 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002437 return res.text
2438 elif(args.type =="cold"):
Justin Thalere412dc22018-01-12 16:28:24 -06002439 print("\nAttempting to reboot the BMC...:")
2440 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06002441 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06002442 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002443 return res.text
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002444 else:
2445 return "invalid command"
Justin Thalere412dc22018-01-12 16:28:24 -06002446
2447def gardClear(host, args, session):
2448 """
2449 clears the gard records from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002450
Justin Thalere412dc22018-01-12 16:28:24 -06002451 @param host: string, the hostname or IP address of the bmc
2452 @param args: contains additional arguments used by the gardClear sub command
2453 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002454 """
Justin Thalere412dc22018-01-12 16:28:24 -06002455 url="https://"+host+"/org/open_power/control/gard/action/Reset"
Justin Thalere412dc22018-01-12 16:28:24 -06002456 data = '{"data":[]}'
2457 try:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002458
Justin Thaler27197622019-01-23 14:42:11 -06002459 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002460 if res.status_code == 404:
2461 return "Command not supported by this firmware version"
2462 else:
2463 return res.text
2464 except(requests.exceptions.Timeout):
2465 return connectionErrHandler(args.json, "Timeout", None)
2466 except(requests.exceptions.ConnectionError) as err:
2467 return connectionErrHandler(args.json, "ConnectionError", err)
2468
2469def activateFWImage(host, args, session):
2470 """
2471 activates a firmware image on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002472
Justin Thalere412dc22018-01-12 16:28:24 -06002473 @param host: string, the hostname or IP address of the bmc
2474 @param args: contains additional arguments used by the fwflash sub command
2475 @param session: the active session to use
2476 @param fwID: the unique ID of the fw image to activate
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002477 """
Justin Thalere412dc22018-01-12 16:28:24 -06002478 fwID = args.imageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002479
Justin Thalere412dc22018-01-12 16:28:24 -06002480 #determine the existing versions
Justin Thalere412dc22018-01-12 16:28:24 -06002481 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2482 try:
Justin Thaler27197622019-01-23 14:42:11 -06002483 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002484 except(requests.exceptions.Timeout):
2485 return connectionErrHandler(args.json, "Timeout", None)
2486 except(requests.exceptions.ConnectionError) as err:
2487 return connectionErrHandler(args.json, "ConnectionError", err)
2488 existingSoftware = json.loads(resp.text)['data']
2489 altVersionID = ''
2490 versionType = ''
2491 imageKey = '/xyz/openbmc_project/software/'+fwID
2492 if imageKey in existingSoftware:
2493 versionType = existingSoftware[imageKey]['Purpose']
2494 for key in existingSoftware:
2495 if imageKey == key:
2496 continue
2497 if 'Purpose' in existingSoftware[key]:
2498 if versionType == existingSoftware[key]['Purpose']:
2499 altVersionID = key.split('/')[-1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002500
2501
2502
2503
Justin Thalere412dc22018-01-12 16:28:24 -06002504 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/attr/Priority"
2505 url1="https://"+host+"/xyz/openbmc_project/software/"+ altVersionID + "/attr/Priority"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002506 data = "{\"data\": 0}"
Justin Thalere412dc22018-01-12 16:28:24 -06002507 data1 = "{\"data\": 1 }"
2508 try:
Justin Thaler27197622019-01-23 14:42:11 -06002509 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
2510 resp1 = session.put(url1, headers=jsonHeader, data=data1, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002511 except(requests.exceptions.Timeout):
2512 return connectionErrHandler(args.json, "Timeout", None)
2513 except(requests.exceptions.ConnectionError) as err:
2514 return connectionErrHandler(args.json, "ConnectionError", err)
2515 if(not args.json):
2516 if resp.status_code == 200 and resp1.status_code == 200:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002517 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 -06002518 else:
2519 return "Firmware activation failed."
2520 else:
2521 return resp.text + resp1.text
Justin Thaler22b1bb52018-03-15 13:31:32 -05002522
2523def activateStatus(host, args, session):
2524 if checkFWactivation(host, args, session):
2525 return("Firmware is currently being activated. Do not reboot the BMC or start the Host OS")
2526 else:
2527 return("No firmware activations are pending")
2528
2529def extractFWimage(path, imageType):
2530 """
2531 extracts the bmc image and returns information about the package
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002532
Justin Thaler22b1bb52018-03-15 13:31:32 -05002533 @param path: the path and file name of the firmware image
2534 @param imageType: The type of image the user is trying to flash. Host or BMC
2535 @return: the image id associated with the package. returns an empty string on error.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002536 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002537 f = tempfile.TemporaryFile()
2538 tmpDir = tempfile.gettempdir()
2539 newImageID = ""
2540 if os.path.exists(path):
2541 try:
2542 imageFile = tarfile.open(path,'r')
2543 contents = imageFile.getmembers()
2544 for tf in contents:
2545 if 'MANIFEST' in tf.name:
2546 imageFile.extract(tf.name, path=tmpDir)
2547 with open(tempfile.gettempdir() +os.sep+ tf.name, 'r') as imageInfo:
2548 for line in imageInfo:
2549 if 'purpose' in line:
2550 purpose = line.split('=')[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002551 if imageType not in purpose.split('.')[-1]:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002552 print('The specified image is not for ' + imageType)
2553 print('Please try again with the image for ' + imageType)
2554 return ""
2555 if 'version' == line.split('=')[0]:
2556 version = line.split('=')[1].strip().encode('utf-8')
2557 m = hashlib.sha512()
2558 m.update(version)
2559 newImageID = m.hexdigest()[:8]
2560 break
2561 try:
2562 os.remove(tempfile.gettempdir() +os.sep+ tf.name)
2563 except OSError:
2564 pass
2565 return newImageID
2566 except tarfile.ExtractError as e:
2567 print('Unable to extract information from the firmware file.')
2568 print('Ensure you have write access to the directory: ' + tmpDir)
2569 return newImageID
2570 except tarfile.TarError as e:
2571 print('This is not a valid firmware file.')
2572 return newImageID
2573 print("This is not a valid firmware file.")
2574 return newImageID
2575 else:
2576 print('The filename and path provided are not valid.')
2577 return newImageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002578
Justin Thaler22b1bb52018-03-15 13:31:32 -05002579def getAllFWImageIDs(fwInvDict):
2580 """
2581 gets a list of all the firmware image IDs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002582
Justin Thaler22b1bb52018-03-15 13:31:32 -05002583 @param fwInvDict: the dictionary to search for FW image IDs
2584 @return: list containing string representation of the found image ids
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002585 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002586 idList = []
2587 for key in fwInvDict:
2588 if 'Version' in fwInvDict[key]:
2589 idList.append(key.split('/')[-1])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002590 return idList
2591
Justin Thalere412dc22018-01-12 16:28:24 -06002592def fwFlash(host, args, session):
2593 """
2594 updates the bmc firmware and pnor firmware
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002595
Justin Thalere412dc22018-01-12 16:28:24 -06002596 @param host: string, the hostname or IP address of the bmc
2597 @param args: contains additional arguments used by the fwflash sub command
2598 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002599 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002600 d = vars(args)
Justin Thalere412dc22018-01-12 16:28:24 -06002601 if(args.type == 'bmc'):
2602 purp = 'BMC'
2603 else:
2604 purp = 'Host'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002605
2606 #check power state of the machine. No concurrent FW updates allowed
Justin Thaler22b1bb52018-03-15 13:31:32 -05002607 d['powcmd'] = 'status'
2608 powerstate = chassisPower(host, args, session)
2609 if 'Chassis Power State: On' in powerstate:
2610 return("Aborting firmware update. Host is powered on. Please turn off the host and try again.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002611
Justin Thaler22b1bb52018-03-15 13:31:32 -05002612 #determine the existing images on the bmc
Justin Thalere412dc22018-01-12 16:28:24 -06002613 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2614 try:
Justin Thaler27197622019-01-23 14:42:11 -06002615 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002616 except(requests.exceptions.Timeout):
2617 return connectionErrHandler(args.json, "Timeout", None)
2618 except(requests.exceptions.ConnectionError) as err:
2619 return connectionErrHandler(args.json, "ConnectionError", err)
2620 oldsoftware = json.loads(resp.text)['data']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002621
Justin Thaler22b1bb52018-03-15 13:31:32 -05002622 #Extract the tar and get information from the manifest file
2623 newversionID = extractFWimage(args.fileloc, purp)
2624 if newversionID == "":
2625 return "Unable to verify FW image."
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002626
2627
Justin Thaler22b1bb52018-03-15 13:31:32 -05002628 #check if the new image is already on the bmc
2629 if newversionID not in getAllFWImageIDs(oldsoftware):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002630
Justin Thaler22b1bb52018-03-15 13:31:32 -05002631 #upload the file
2632 httpHeader = {'Content-Type':'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002633 httpHeader.update(xAuthHeader)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002634 url="https://"+host+"/upload/image"
2635 data=open(args.fileloc,'rb').read()
2636 print("Uploading file to BMC")
Justin Thalere412dc22018-01-12 16:28:24 -06002637 try:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002638 resp = session.post(url, headers=httpHeader, data=data, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -06002639 except(requests.exceptions.Timeout):
2640 return connectionErrHandler(args.json, "Timeout", None)
2641 except(requests.exceptions.ConnectionError) as err:
2642 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002643 if resp.status_code != 200:
2644 return "Failed to upload the file to the bmc"
Justin Thalere412dc22018-01-12 16:28:24 -06002645 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002646 print("Upload complete.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002647
Justin Thaler22b1bb52018-03-15 13:31:32 -05002648 #verify bmc processed the image
2649 software ={}
2650 for i in range(0, 5):
Justin Thaler22b1bb52018-03-15 13:31:32 -05002651 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2652 try:
Justin Thaler27197622019-01-23 14:42:11 -06002653 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002654 except(requests.exceptions.Timeout):
2655 return connectionErrHandler(args.json, "Timeout", None)
2656 except(requests.exceptions.ConnectionError) as err:
2657 return connectionErrHandler(args.json, "ConnectionError", err)
2658 software = json.loads(resp.text)['data']
2659 #check if bmc is done processing the new image
2660 if (newversionID in getAllFWImageIDs(software)):
Justin Thalere412dc22018-01-12 16:28:24 -06002661 break
Justin Thaler22b1bb52018-03-15 13:31:32 -05002662 else:
2663 time.sleep(15)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002664
Justin Thaler22b1bb52018-03-15 13:31:32 -05002665 #activate the new image
2666 print("Activating new image: "+newversionID)
2667 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID + "/attr/RequestedActivation"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002668 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05002669 try:
Justin Thaler27197622019-01-23 14:42:11 -06002670 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002671 except(requests.exceptions.Timeout):
2672 return connectionErrHandler(args.json, "Timeout", None)
2673 except(requests.exceptions.ConnectionError) as err:
2674 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002675
Justin Thaler22b1bb52018-03-15 13:31:32 -05002676 #wait for the activation to complete, timeout after ~1 hour
2677 i=0
2678 while i < 360:
2679 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002680 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05002681 try:
Justin Thaler27197622019-01-23 14:42:11 -06002682 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002683 except(requests.exceptions.Timeout):
2684 return connectionErrHandler(args.json, "Timeout", None)
2685 except(requests.exceptions.ConnectionError) as err:
2686 return connectionErrHandler(args.json, "ConnectionError", err)
2687 fwInfo = json.loads(resp.text)['data']
2688 if 'Activating' not in fwInfo['Activation'] and 'Activating' not in fwInfo['RequestedActivation']:
2689 print('')
2690 break
2691 else:
2692 sys.stdout.write('.')
2693 sys.stdout.flush()
2694 time.sleep(10) #check every 10 seconds
2695 return "Firmware flash and activation completed. Please reboot the bmc and then boot the host OS for the changes to take effect. "
2696 else:
2697 print("This image has been found on the bmc. Activating image: " + newversionID)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002698
Justin Thaler22b1bb52018-03-15 13:31:32 -05002699 d['imageID'] = newversionID
2700 return activateFWImage(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06002701
Justin Thaler3d71d402018-07-24 14:35:39 -05002702def getFWInventoryAttributes(rawFWInvItem, ID):
2703 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002704 gets and lists all of the firmware in the system.
2705
Justin Thaler3d71d402018-07-24 14:35:39 -05002706 @return: returns a dictionary containing the image attributes
2707 """
2708 reqActivation = rawFWInvItem["RequestedActivation"].split('.')[-1]
2709 pendingActivation = ""
2710 if reqActivation == "None":
2711 pendingActivation = "No"
2712 else:
2713 pendingActivation = "Yes"
2714 firmwareAttr = {ID: {
2715 "Purpose": rawFWInvItem["Purpose"].split('.')[-1],
2716 "Version": rawFWInvItem["Version"],
2717 "RequestedActivation": pendingActivation,
2718 "ID": ID}}
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002719
Justin Thaler3d71d402018-07-24 14:35:39 -05002720 if "ExtendedVersion" in rawFWInvItem:
2721 firmwareAttr[ID]['ExtendedVersion'] = rawFWInvItem['ExtendedVersion'].split(',')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002722 else:
Justin Thaler3d71d402018-07-24 14:35:39 -05002723 firmwareAttr[ID]['ExtendedVersion'] = ""
2724 return firmwareAttr
2725
2726def parseFWdata(firmwareDict):
2727 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002728 creates a dictionary with parsed firmware data
2729
Justin Thaler3d71d402018-07-24 14:35:39 -05002730 @return: returns a dictionary containing the image attributes
2731 """
2732 firmwareInfoDict = {"Functional": {}, "Activated":{}, "NeedsActivated":{}}
2733 for key in firmwareDict['data']:
2734 #check for valid endpoint
2735 if "Purpose" in firmwareDict['data'][key]:
2736 id = key.split('/')[-1]
2737 if firmwareDict['data'][key]['Activation'].split('.')[-1] == "Active":
2738 fwActivated = True
2739 else:
2740 fwActivated = False
Justin Thalercb68e062019-03-26 19:04:52 -05002741 if 'Priority' in firmwareDict['data'][key]:
2742 if firmwareDict['data'][key]['Priority'] == 0:
2743 firmwareInfoDict['Functional'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2744 elif firmwareDict['data'][key]['Priority'] >= 0 and fwActivated:
2745 firmwareInfoDict['Activated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2746 else:
2747 firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
Justin Thaler3d71d402018-07-24 14:35:39 -05002748 else:
Justin Thalercb68e062019-03-26 19:04:52 -05002749 firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
Justin Thaler3d71d402018-07-24 14:35:39 -05002750 emptySections = []
2751 for key in firmwareInfoDict:
2752 if len(firmwareInfoDict[key])<=0:
2753 emptySections.append(key)
2754 for key in emptySections:
2755 del firmwareInfoDict[key]
2756 return firmwareInfoDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002757
Justin Thaler3d71d402018-07-24 14:35:39 -05002758def displayFWInvenory(firmwareInfoDict, args):
2759 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002760 gets and lists all of the firmware in the system.
2761
Justin Thaler3d71d402018-07-24 14:35:39 -05002762 @return: returns a string containing all of the firmware information
2763 """
2764 output = ""
2765 if not args.json:
2766 for key in firmwareInfoDict:
2767 for subkey in firmwareInfoDict[key]:
2768 firmwareInfoDict[key][subkey]['ExtendedVersion'] = str(firmwareInfoDict[key][subkey]['ExtendedVersion'])
2769 if not args.verbose:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002770 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002771 colNames = ["Purpose", "Version", "ID"]
2772 keylist = ["Purpose", "Version", "ID"]
2773 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2774 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002775 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002776 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2777 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002778 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002779 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002780
Justin Thaler3d71d402018-07-24 14:35:39 -05002781 else:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002782 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002783 colNames = ["Purpose", "Version", "ID", "Pending Activation", "Extended Version"]
2784 keylist = ["Purpose", "Version", "ID", "RequestedActivation", "ExtendedVersion"]
2785 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2786 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002787 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002788 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2789 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002790 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002791 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
2792 return output
2793 else:
2794 return str(json.dumps(firmwareInfoDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
2795
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002796def firmwareList(host, args, session):
Justin Thaler3d71d402018-07-24 14:35:39 -05002797 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002798 gets and lists all of the firmware in the system.
2799
Justin Thaler3d71d402018-07-24 14:35:39 -05002800 @return: returns a string containing all of the firmware information
2801 """
Justin Thaler3d71d402018-07-24 14:35:39 -05002802 url="https://{hostname}/xyz/openbmc_project/software/enumerate".format(hostname=host)
2803 try:
Justin Thaler27197622019-01-23 14:42:11 -06002804 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3d71d402018-07-24 14:35:39 -05002805 except(requests.exceptions.Timeout):
2806 return(connectionErrHandler(args.json, "Timeout", None))
2807 firmwareDict = json.loads(res.text)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002808
Justin Thaler3d71d402018-07-24 14:35:39 -05002809 #sort the received information
2810 firmwareInfoDict = parseFWdata(firmwareDict)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002811
Justin Thaler3d71d402018-07-24 14:35:39 -05002812 #display the information
2813 return displayFWInvenory(firmwareInfoDict, args)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002814
2815
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002816def deleteFWVersion(host, args, session):
2817 """
2818 deletes a firmware version on the BMC
2819
2820 @param host: string, the hostname or IP address of the BMC
2821 @param args: contains additional arguments used by the fwflash sub command
2822 @param session: the active session to use
2823 @param fwID: the unique ID of the fw version to delete
2824 """
2825 fwID = args.versionID
2826
2827 print("Deleting version: "+fwID)
2828 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/action/Delete"
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002829 data = "{\"data\": [] }"
2830
2831 try:
Justin Thaler27197622019-01-23 14:42:11 -06002832 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002833 except(requests.exceptions.Timeout):
2834 return(connectionErrHandler(args.json, "Timeout", None))
2835 if res.status_code == 200:
2836 return ('The firmware version has been deleted')
2837 else:
2838 return ('Unable to delete the specified firmware version')
2839
2840
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002841def restLogging(host, args, session):
2842 """
2843 Called by the logging function. Turns REST API logging on/off.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002844
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002845 @param host: string, the hostname or IP address of the bmc
2846 @param args: contains additional arguments used by the logging sub command
2847 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002848 @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 -05002849 """
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002850 url="https://"+host+"/xyz/openbmc_project/logging/rest_api_logs/attr/Enabled"
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002851
2852 if(args.rest_logging == 'on'):
2853 data = '{"data": 1}'
2854 elif(args.rest_logging == 'off'):
2855 data = '{"data": 0}'
2856 else:
2857 return "Invalid logging rest_api command"
2858
2859 try:
Justin Thaler27197622019-01-23 14:42:11 -06002860 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002861 except(requests.exceptions.Timeout):
2862 return(connectionErrHandler(args.json, "Timeout", None))
2863 return res.text
2864
2865
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002866def remoteLogging(host, args, session):
2867 """
2868 Called by the logging function. View config information for/disable remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002869
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002870 @param host: string, the hostname or IP address of the bmc
2871 @param args: contains additional arguments used by the logging sub command
2872 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002873 @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 -05002874 """
2875
2876 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002877
2878 try:
2879 if(args.remote_logging == 'view'):
Justin Thaler27197622019-01-23 14:42:11 -06002880 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002881 elif(args.remote_logging == 'disable'):
Justin Thaler27197622019-01-23 14:42:11 -06002882 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": 0}, verify=False, timeout=baseTimeout)
2883 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": ""}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002884 else:
2885 return "Invalid logging remote_logging command"
2886 except(requests.exceptions.Timeout):
2887 return(connectionErrHandler(args.json, "Timeout", None))
2888 return res.text
2889
2890
2891def remoteLoggingConfig(host, args, session):
2892 """
2893 Called by the logging function. Configures remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002894
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002895 @param host: string, the hostname or IP address of the bmc
2896 @param args: contains additional arguments used by the logging sub command
2897 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002898 @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 -05002899 """
2900
2901 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002902
2903 try:
Justin Thaler27197622019-01-23 14:42:11 -06002904 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": args.port}, verify=False, timeout=baseTimeout)
2905 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": args.address}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002906 except(requests.exceptions.Timeout):
2907 return(connectionErrHandler(args.json, "Timeout", None))
2908 return res.text
2909
Marri Devender Rao82590dc2019-06-06 04:54:22 -05002910def redfishSupportPresent(host, session):
2911 url = "https://" + host + "/redfish/v1"
2912 try:
2913 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
2914 except(requests.exceptions.Timeout):
2915 return False
2916 except(requests.exceptions.ConnectionError) as err:
2917 return False
2918 if resp.status_code != 200:
2919 return False
2920 else:
2921 return True
Ratan Gupta9166cd22018-10-01 18:09:40 +05302922
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002923def certificateUpdate(host, args, session):
2924 """
2925 Called by certificate management function. update server/client/authority certificates
2926 Example:
2927 certificate update server https -f cert.pem
2928 certificate update authority ldap -f Root-CA.pem
2929 certificate update client ldap -f cert.pem
2930 @param host: string, the hostname or IP address of the bmc
2931 @param args: contains additional arguments used by the certificate update sub command
2932 @param session: the active session to use
2933 """
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002934 httpHeader = {'Content-Type': 'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002935 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002936 data = open(args.fileloc, 'rb').read()
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002937 try:
Marri Devender Rao82590dc2019-06-06 04:54:22 -05002938 if redfishSupportPresent(host, session):
Marri Devender Rao62db08a2019-08-22 03:16:02 -05002939 if(args.type.lower() == 'server' and args.service.lower() != "https"):
2940 return "Invalid service type"
2941 if(args.type.lower() == 'client' and args.service.lower() != "ldap"):
2942 return "Invalid service type"
2943 if(args.type.lower() == 'authority' and args.service.lower() != "ldap"):
2944 return "Invalid service type"
Marri Devender Rao82590dc2019-06-06 04:54:22 -05002945 url = "";
2946 if(args.type.lower() == 'server'):
2947 url = "https://" + host + \
2948 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"
2949 elif(args.type.lower() == 'client'):
2950 url = "https://" + host + \
2951 "/redfish/v1/AccountService/LDAP/Certificates"
2952 elif(args.type.lower() == 'authority'):
2953 url = "https://" + host + \
2954 "/redfish/v1/Managers/bmc/Truststore/Certificates"
2955 else:
2956 return "Unsupported certificate type"
2957 resp = session.post(url, headers=httpHeader, data=data,
2958 verify=False)
2959 else:
2960 url = "https://" + host + "/xyz/openbmc_project/certs/" + \
2961 args.type.lower() + "/" + args.service.lower()
2962 resp = session.put(url, headers=httpHeader, data=data, verify=False)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002963 except(requests.exceptions.Timeout):
2964 return(connectionErrHandler(args.json, "Timeout", None))
2965 except(requests.exceptions.ConnectionError) as err:
2966 return connectionErrHandler(args.json, "ConnectionError", err)
2967 if resp.status_code != 200:
2968 print(resp.text)
2969 return "Failed to update the certificate"
2970 else:
Marri Devender Rao82590dc2019-06-06 04:54:22 -05002971 print("Update complete.")
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002972
2973def certificateDelete(host, args, session):
2974 """
2975 Called by certificate management function to delete certificate
2976 Example:
2977 certificate delete server https
2978 certificate delete authority ldap
2979 certificate delete client ldap
2980 @param host: string, the hostname or IP address of the bmc
2981 @param args: contains additional arguments used by the certificate delete sub command
2982 @param session: the active session to use
2983 """
Marri Devender Rao77e78682019-07-17 03:18:35 -05002984 if redfishSupportPresent(host, session):
2985 return "Not supported, please use certificate replace instead";
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002986 httpHeader = {'Content-Type': 'multipart/form-data'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002987 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002988 url = "https://" + host + "/xyz/openbmc_project/certs/" + args.type.lower() + "/" + args.service.lower()
2989 print("Deleting certificate url=" + url)
2990 try:
2991 resp = session.delete(url, headers=httpHeader)
2992 except(requests.exceptions.Timeout):
2993 return(connectionErrHandler(args.json, "Timeout", None))
2994 except(requests.exceptions.ConnectionError) as err:
2995 return connectionErrHandler(args.json, "ConnectionError", err)
2996 if resp.status_code != 200:
2997 print(resp.text)
2998 return "Failed to delete the certificate"
2999 else:
Marri Devender Rao77e78682019-07-17 03:18:35 -05003000 print("Delete complete.")
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003001
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05003002def certificateReplace(host, args, session):
3003 """
3004 Called by certificate management function. replace server/client/
3005 authority certificates
3006 Example:
3007 certificate replace server https -f cert.pem
3008 certificate replace authority ldap -f Root-CA.pem
3009 certificate replace client ldap -f cert.pem
3010 @param host: string, the hostname or IP address of the bmc
3011 @param args: contains additional arguments used by the certificate
3012 replace sub command
3013 @param session: the active session to use
3014 """
3015 cert = open(args.fileloc, 'rb').read()
3016 try:
3017 if redfishSupportPresent(host, session):
3018 httpHeader = {'Content-Type': 'application/json'}
3019 httpHeader.update(xAuthHeader)
3020 url = "";
Marri Devender Rao62db08a2019-08-22 03:16:02 -05003021 if(args.type.lower() == 'server' and args.service.lower() != "https"):
3022 return "Invalid service type"
3023 if(args.type.lower() == 'client' and args.service.lower() != "ldap"):
3024 return "Invalid service type"
3025 if(args.type.lower() == 'authority' and args.service.lower() != "ldap"):
3026 return "Invalid service type"
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05003027 if(args.type.lower() == 'server'):
3028 url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
3029 elif(args.type.lower() == 'client'):
3030 url = "/redfish/v1/AccountService/LDAP/Certificates/1"
3031 elif(args.type.lower() == 'authority'):
3032 url = "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
3033 replaceUrl = "https://" + host + \
3034 "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"
3035 data ={"CertificateUri":{"@odata.id":url}, "CertificateType":"PEM",
3036 "CertificateString":cert}
3037 resp = session.post(replaceUrl, headers=httpHeader, json=data, verify=False)
3038 else:
3039 httpHeader = {'Content-Type': 'application/octet-stream'}
3040 httpHeader.update(xAuthHeader)
3041 url = "https://" + host + "/xyz/openbmc_project/certs/" + \
3042 args.type.lower() + "/" + args.service.lower()
3043 resp = session.delete(url, headers=httpHeader)
3044 resp = session.put(url, headers=httpHeader, data=cert, verify=False)
3045 except(requests.exceptions.Timeout):
3046 return(connectionErrHandler(args.json, "Timeout", None))
3047 except(requests.exceptions.ConnectionError) as err:
3048 return connectionErrHandler(args.json, "ConnectionError", err)
3049 if resp.status_code != 200:
3050 print(resp.text)
3051 return "Failed to replace the certificate"
3052 else:
3053 print("Replace complete.")
3054 return resp.text
3055
Marri Devender Rao34646402019-07-01 05:46:03 -05003056def certificateDisplay(host, args, session):
3057 """
3058 Called by certificate management function. display server/client/
3059 authority certificates
3060 Example:
3061 certificate display server
3062 certificate display authority
3063 certificate display client
3064 @param host: string, the hostname or IP address of the bmc
3065 @param args: contains additional arguments used by the certificate
3066 display sub command
3067 @param session: the active session to use
3068 """
3069 if not redfishSupportPresent(host, session):
3070 return "Not supported";
3071
3072 httpHeader = {'Content-Type': 'application/octet-stream'}
3073 httpHeader.update(xAuthHeader)
3074 if(args.type.lower() == 'server'):
3075 url = "https://" + host + \
3076 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
3077 elif(args.type.lower() == 'client'):
3078 url = "https://" + host + \
3079 "/redfish/v1/AccountService/LDAP/Certificates/1"
3080 elif(args.type.lower() == 'authority'):
3081 url = "https://" + host + \
3082 "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
3083 try:
3084 resp = session.get(url, headers=httpHeader, verify=False)
3085 except(requests.exceptions.Timeout):
3086 return(connectionErrHandler(args.json, "Timeout", None))
3087 except(requests.exceptions.ConnectionError) as err:
3088 return connectionErrHandler(args.json, "ConnectionError", err)
3089 if resp.status_code != 200:
3090 print(resp.text)
3091 return "Failed to display the certificate"
3092 else:
3093 print("Display complete.")
3094 return resp.text
3095
Marri Devender Raoa208ff82019-07-01 05:51:27 -05003096def certificateList(host, args, session):
3097 """
3098 Called by certificate management function.
3099 Example:
3100 certificate list
3101 @param host: string, the hostname or IP address of the bmc
3102 @param args: contains additional arguments used by the certificate
3103 list sub command
3104 @param session: the active session to use
3105 """
3106 if not redfishSupportPresent(host, session):
3107 return "Not supported";
3108
3109 httpHeader = {'Content-Type': 'application/octet-stream'}
3110 httpHeader.update(xAuthHeader)
3111 url = "https://" + host + \
3112 "/redfish/v1/CertificateService/CertificateLocations/"
3113 try:
3114 resp = session.get(url, headers=httpHeader, verify=False)
3115 except(requests.exceptions.Timeout):
3116 return(connectionErrHandler(args.json, "Timeout", None))
3117 except(requests.exceptions.ConnectionError) as err:
3118 return connectionErrHandler(args.json, "ConnectionError", err)
3119 if resp.status_code != 200:
3120 print(resp.text)
3121 return "Failed to list certificates"
3122 else:
3123 print("List certificates complete.")
3124 return resp.text
3125
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003126def certificateGenerateCSR(host, args, session):
3127 """
3128 Called by certificate management function. Generate CSR for server/
3129 client certificates
3130 Example:
Marri Devender Raodf0e1a42019-09-09 08:18:27 -05003131 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
3132 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 -05003133 @param host: string, the hostname or IP address of the bmc
3134 @param args: contains additional arguments used by the certificate replace sub command
3135 @param session: the active session to use
3136 """
3137 if not redfishSupportPresent(host, session):
3138 return "Not supported";
3139
3140 httpHeader = {'Content-Type': 'application/octet-stream'}
3141 httpHeader.update(xAuthHeader)
3142 url = "";
3143 if(args.type.lower() == 'server'):
3144 url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
Marri Devender Rao88064f02019-08-19 09:00:30 -05003145 usage_list = ["ServerAuthentication"]
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003146 elif(args.type.lower() == 'client'):
3147 url = "/redfish/v1/AccountService/LDAP/Certificates/"
Marri Devender Rao88064f02019-08-19 09:00:30 -05003148 usage_list = ["ClientAuthentication"]
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003149 elif(args.type.lower() == 'authority'):
3150 url = "/redfish/v1/Managers/bmc/Truststore/Certificates/"
3151 print("Generating CSR url=" + url)
3152 generateCSRUrl = "https://" + host + \
3153 "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"
3154 try:
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003155 alt_name_list = args.alternativeNames.split(",")
3156 data ={"CertificateCollection":{"@odata.id":url},
3157 "CommonName":args.commonName, "City":args.city,
3158 "Country":args.country, "Organization":args.organization,
3159 "OrganizationalUnit":args.organizationUnit, "State":args.state,
Marri Devender Raodf0e1a42019-09-09 08:18:27 -05003160 "KeyPairAlgorithm":args.keyPairAlgorithm, "KeyCurveId":args.keyCurveId,
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003161 "AlternativeNames":alt_name_list, "ContactPerson":args.contactPerson,
3162 "Email":args.email, "GivenName":args.givenname, "Initials":args.initials,
3163 "KeyUsage":usage_list, "Surname":args.surname,
3164 "UnstructuredName":args.unstructuredname}
3165 resp = session.post(generateCSRUrl, headers=httpHeader,
3166 json=data, verify=False)
3167 except(requests.exceptions.Timeout):
3168 return(connectionErrHandler(args.json, "Timeout", None))
3169 except(requests.exceptions.ConnectionError) as err:
3170 return connectionErrHandler(args.json, "ConnectionError", err)
3171 if resp.status_code != 200:
3172 print(resp.text)
3173 return "Failed to generate CSR"
3174 else:
3175 print("GenerateCSR complete.")
3176 return resp.text
3177
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003178def enableLDAPConfig(host, args, session):
Ratan Gupta9166cd22018-10-01 18:09:40 +05303179 """
3180 Called by the ldap function. Configures LDAP.
3181
3182 @param host: string, the hostname or IP address of the bmc
3183 @param args: contains additional arguments used by the ldap subcommand
3184 @param session: the active session to use
3185 @param args.json: boolean, if this flag is set to true, the output will
3186 be provided in json format for programmatic consumption
3187 """
3188
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003189 if(isRedfishSupport):
3190 return enableLDAP(host, args, session)
3191 else:
3192 return enableLegacyLDAP(host, args, session)
3193
3194def enableLegacyLDAP(host, args, session):
3195 """
3196 Called by the ldap function. Configures LDAP on Lagecy systems.
3197
3198 @param host: string, the hostname or IP address of the bmc
3199 @param args: contains additional arguments used by the ldap subcommand
3200 @param session: the active session to use
3201 @param args.json: boolean, if this flag is set to true, the output will
3202 be provided in json format for programmatic consumption
3203 """
3204
Ratan Gupta9166cd22018-10-01 18:09:40 +05303205 url='https://'+host+'/xyz/openbmc_project/user/ldap/action/CreateConfig'
Ratan Gupta9166cd22018-10-01 18:09:40 +05303206 scope = {
3207 'sub' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.sub',
3208 'one' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.one',
3209 'base': 'xyz.openbmc_project.User.Ldap.Create.SearchScope.base'
3210 }
3211
3212 serverType = {
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003213 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Create.Type.ActiveDirectory',
3214 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Create.Type.OpenLdap'
Ratan Gupta9166cd22018-10-01 18:09:40 +05303215 }
3216
3217 data = {"data": [args.uri, args.bindDN, args.baseDN, args.bindPassword, scope[args.scope], serverType[args.serverType]]}
3218
3219 try:
Justin Thaler27197622019-01-23 14:42:11 -06003220 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Ratan Gupta9166cd22018-10-01 18:09:40 +05303221 except(requests.exceptions.Timeout):
3222 return(connectionErrHandler(args.json, "Timeout", None))
3223 except(requests.exceptions.ConnectionError) as err:
3224 return connectionErrHandler(args.json, "ConnectionError", err)
3225
3226 return res.text
3227
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003228def enableLDAP(host, args, session):
3229 """
3230 Called by the ldap function. Configures LDAP for systems with latest user-manager design changes
3231
3232 @param host: string, the hostname or IP address of the bmc
3233 @param args: contains additional arguments used by the ldap subcommand
3234 @param session: the active session to use
3235 @param args.json: boolean, if this flag is set to true, the output will
3236 be provided in json format for programmatic consumption
3237 """
3238
3239 scope = {
3240 'sub' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.sub',
3241 'one' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.one',
3242 'base': 'xyz.openbmc_project.User.Ldap.Config.SearchScope.base'
3243 }
3244
3245 serverType = {
3246 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Config.Type.ActiveDirectory',
3247 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap'
3248 }
3249
3250 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
3251
3252 serverTypeEnabled = getLDAPTypeEnabled(host,session)
3253 serverTypeToBeEnabled = args.serverType
3254
3255 #If the given LDAP type is already enabled, then return
3256 if (serverTypeToBeEnabled == serverTypeEnabled):
3257 return("Server type " + serverTypeToBeEnabled + " is already enabled...")
3258
3259 try:
3260
3261 # Copy the role map from the currently enabled LDAP server type
3262 # to the newly enabled server type
3263 # Disable the currently enabled LDAP server type. Unless
3264 # it is disabled, we cannot enable a new LDAP server type
3265 if (serverTypeEnabled is not None):
3266
3267 if (serverTypeToBeEnabled != serverTypeEnabled):
3268 res = syncRoleMap(host,args,session,serverTypeEnabled,serverTypeToBeEnabled)
3269
3270 data = "{\"data\": 0 }"
3271 res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3272
3273 data = {"data": args.baseDN}
3274 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBaseDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3275 if (res.status_code != requests.codes.ok):
3276 print("Updates to the property LDAPBaseDN failed...")
3277 return(res.text)
3278
3279 data = {"data": args.bindDN}
3280 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3281 if (res.status_code != requests.codes.ok):
3282 print("Updates to the property LDAPBindDN failed...")
3283 return(res.text)
3284
3285 data = {"data": args.bindPassword}
3286 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDNPassword', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3287 if (res.status_code != requests.codes.ok):
3288 print("Updates to the property LDAPBindDNPassword failed...")
3289 return(res.text)
3290
3291 data = {"data": scope[args.scope]}
3292 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPSearchScope', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3293 if (res.status_code != requests.codes.ok):
3294 print("Updates to the property LDAPSearchScope failed...")
3295 return(res.text)
3296
3297 data = {"data": args.uri}
3298 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPServerURI', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3299 if (res.status_code != requests.codes.ok):
3300 print("Updates to the property LDAPServerURI failed...")
3301 return(res.text)
3302
3303 data = {"data": args.groupAttrName}
3304 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/GroupNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3305 if (res.status_code != requests.codes.ok):
3306 print("Updates to the property GroupNameAttribute failed...")
3307 return(res.text)
3308
3309 data = {"data": args.userAttrName}
3310 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/UserNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3311 if (res.status_code != requests.codes.ok):
3312 print("Updates to the property UserNameAttribute failed...")
3313 return(res.text)
3314
3315 #After updating the properties, enable the new server type
3316 data = "{\"data\": 1 }"
3317 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3318
3319 except(requests.exceptions.Timeout):
3320 return(connectionErrHandler(args.json, "Timeout", None))
3321 except(requests.exceptions.ConnectionError) as err:
3322 return connectionErrHandler(args.json, "ConnectionError", err)
3323 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05303324
3325def disableLDAP(host, args, session):
3326 """
3327 Called by the ldap function. Deletes the LDAP Configuration.
3328
3329 @param host: string, the hostname or IP address of the bmc
3330 @param args: contains additional arguments used by the ldap subcommand
3331 @param session: the active session to use
3332 @param args.json: boolean, if this flag is set to true, the output
3333 will be provided in json format for programmatic consumption
3334 """
3335
Ratan Gupta9166cd22018-10-01 18:09:40 +05303336 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003337 if (isRedfishSupport) :
3338
3339 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
3340
3341 serverTypeEnabled = getLDAPTypeEnabled(host,session)
3342
3343 if (serverTypeEnabled is not None):
3344 #To keep the role map in sync,
3345 #If the server type being disabled has role map, then
3346 # - copy the role map to the other server type(s)
3347 for serverType in serverTypeMap.keys():
3348 if (serverType != serverTypeEnabled):
3349 res = syncRoleMap(host,args,session,serverTypeEnabled,serverType)
3350
3351 #Disable the currently enabled LDAP server type
3352 data = "{\"data\": 0 }"
3353 res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3354
3355 else:
3356 return("LDAP server has not been enabled...")
3357
3358 else :
3359 url='https://'+host+'/xyz/openbmc_project/user/ldap/config/action/delete'
3360 data = {"data": []}
3361 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3362
Ratan Gupta9166cd22018-10-01 18:09:40 +05303363 except(requests.exceptions.Timeout):
3364 return(connectionErrHandler(args.json, "Timeout", None))
3365 except(requests.exceptions.ConnectionError) as err:
3366 return connectionErrHandler(args.json, "ConnectionError", err)
3367
3368 return res.text
3369
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003370def enableDHCP(host, args, session):
3371
3372 """
3373 Called by the network function. Enables DHCP.
3374
3375 @param host: string, the hostname or IP address of the bmc
3376 @param args: contains additional arguments used by the ldap subcommand
3377 args.json: boolean, if this flag is set to true, the output
3378 will be provided in json format for programmatic consumption
3379 @param session: the active session to use
3380 """
3381
3382 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3383 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003384 data = "{\"data\": 1 }"
3385 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003386 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003387 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003388
3389 except(requests.exceptions.Timeout):
3390 return(connectionErrHandler(args.json, "Timeout", None))
3391 except(requests.exceptions.ConnectionError) as err:
3392 return connectionErrHandler(args.json, "ConnectionError", err)
3393 if res.status_code == 403:
3394 return "The specified Interface"+"("+args.Interface+")"+\
3395 " doesn't exist"
3396
3397 return res.text
3398
3399
3400def disableDHCP(host, args, session):
3401 """
3402 Called by the network function. Disables DHCP.
3403
3404 @param host: string, the hostname or IP address of the bmc
3405 @param args: contains additional arguments used by the ldap subcommand
3406 args.json: boolean, if this flag is set to true, the output
3407 will be provided in json format for programmatic consumption
3408 @param session: the active session to use
3409 """
3410
3411 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3412 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003413 data = "{\"data\": 0 }"
3414 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003415 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003416 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003417 except(requests.exceptions.Timeout):
3418 return(connectionErrHandler(args.json, "Timeout", None))
3419 except(requests.exceptions.ConnectionError) as err:
3420 return connectionErrHandler(args.json, "ConnectionError", err)
3421 if res.status_code == 403:
3422 return "The specified Interface"+"("+args.Interface+")"+\
3423 " doesn't exist"
3424 return res.text
3425
3426
3427def getHostname(host, args, session):
3428
3429 """
3430 Called by the network function. Prints out the Hostname.
3431
3432 @param host: string, the hostname or IP address of the bmc
3433 @param args: contains additional arguments used by the ldap subcommand
3434 args.json: boolean, if this flag is set to true, the output
3435 will be provided in json format for programmatic consumption
3436 @param session: the active session to use
3437 """
3438
3439 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003440
3441 try:
Justin Thaler27197622019-01-23 14:42:11 -06003442 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003443 except(requests.exceptions.Timeout):
3444 return(connectionErrHandler(args.json, "Timeout", None))
3445 except(requests.exceptions.ConnectionError) as err:
3446 return connectionErrHandler(args.json, "ConnectionError", err)
3447
3448 return res.text
3449
3450
3451def setHostname(host, args, session):
3452 """
3453 Called by the network function. Sets the Hostname.
3454
3455 @param host: string, the hostname or IP address of the bmc
3456 @param args: contains additional arguments used by the ldap subcommand
3457 args.json: boolean, if this flag is set to true, the output
3458 will be provided in json format for programmatic consumption
3459 @param session: the active session to use
3460 """
3461
3462 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003463
3464 data = {"data": args.HostName}
3465
3466 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003467 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003468 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003469 except(requests.exceptions.Timeout):
3470 return(connectionErrHandler(args.json, "Timeout", None))
3471 except(requests.exceptions.ConnectionError) as err:
3472 return connectionErrHandler(args.json, "ConnectionError", err)
3473
3474 return res.text
3475
3476
3477def getDomainName(host, args, session):
3478
3479 """
3480 Called by the network function. Prints out the DomainName.
3481
3482 @param host: string, the hostname or IP address of the bmc
3483 @param args: contains additional arguments used by the ldap subcommand
3484 args.json: boolean, if this flag is set to true, the output
3485 will be provided in json format for programmatic consumption
3486 @param session: the active session to use
3487 """
3488
3489 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3490 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003491
3492 try:
Justin Thaler27197622019-01-23 14:42:11 -06003493 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003494 except(requests.exceptions.Timeout):
3495 return(connectionErrHandler(args.json, "Timeout", None))
3496 except(requests.exceptions.ConnectionError) as err:
3497 return connectionErrHandler(args.json, "ConnectionError", err)
3498 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003499 return "The DomainName is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003500
3501 return res.text
3502
3503
3504def setDomainName(host, args, session):
3505 """
3506 Called by the network function. Sets the DomainName.
3507
3508 @param host: string, the hostname or IP address of the bmc
3509 @param args: contains additional arguments used by the ldap subcommand
3510 args.json: boolean, if this flag is set to true, the output
3511 will be provided in json format for programmatic consumption
3512 @param session: the active session to use
3513 """
3514
3515 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3516 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003517
3518 data = {"data": args.DomainName.split(",")}
3519
3520 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003521 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003522 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003523 except(requests.exceptions.Timeout):
3524 return(connectionErrHandler(args.json, "Timeout", None))
3525 except(requests.exceptions.ConnectionError) as err:
3526 return connectionErrHandler(args.json, "ConnectionError", err)
3527 if res.status_code == 403:
3528 return "The specified Interface"+"("+args.Interface+")"+\
3529 " doesn't exist"
3530
3531 return res.text
3532
3533
3534def getMACAddress(host, args, session):
3535
3536 """
3537 Called by the network function. Prints out the MACAddress.
3538
3539 @param host: string, the hostname or IP address of the bmc
3540 @param args: contains additional arguments used by the ldap subcommand
3541 args.json: boolean, if this flag is set to true, the output
3542 will be provided in json format for programmatic consumption
3543 @param session: the active session to use
3544 """
3545
3546 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3547 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003548
3549 try:
Justin Thaler27197622019-01-23 14:42:11 -06003550 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003551 except(requests.exceptions.Timeout):
3552 return(connectionErrHandler(args.json, "Timeout", None))
3553 except(requests.exceptions.ConnectionError) as err:
3554 return connectionErrHandler(args.json, "ConnectionError", err)
3555 if res.status_code == 404:
3556 return "The specified Interface"+"("+args.Interface+")"+\
3557 " doesn't exist"
3558
3559 return res.text
3560
3561
3562def setMACAddress(host, args, session):
3563 """
3564 Called by the network function. Sets the MACAddress.
3565
3566 @param host: string, the hostname or IP address of the bmc
3567 @param args: contains additional arguments used by the ldap subcommand
3568 args.json: boolean, if this flag is set to true, the output
3569 will be provided in json format for programmatic consumption
3570 @param session: the active session to use
3571 """
3572
3573 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3574 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003575
3576 data = {"data": args.MACAddress}
3577
3578 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003579 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003580 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003581 except(requests.exceptions.Timeout):
3582 return(connectionErrHandler(args.json, "Timeout", None))
3583 except(requests.exceptions.ConnectionError) as err:
3584 return connectionErrHandler(args.json, "ConnectionError", err)
3585 if res.status_code == 403:
3586 return "The specified Interface"+"("+args.Interface+")"+\
3587 " doesn't exist"
3588
3589 return res.text
3590
3591
3592def getDefaultGateway(host, args, session):
3593
3594 """
3595 Called by the network function. Prints out the DefaultGateway.
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/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003605
3606 try:
Justin Thaler27197622019-01-23 14:42:11 -06003607 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003608 except(requests.exceptions.Timeout):
3609 return(connectionErrHandler(args.json, "Timeout", None))
3610 except(requests.exceptions.ConnectionError) as err:
3611 return connectionErrHandler(args.json, "ConnectionError", err)
3612 if res.status_code == 404:
3613 return "Failed to get Default Gateway info!!"
3614
3615 return res.text
3616
3617
3618def setDefaultGateway(host, args, session):
3619 """
3620 Called by the network function. Sets the DefaultGateway.
3621
3622 @param host: string, the hostname or IP address of the bmc
3623 @param args: contains additional arguments used by the ldap subcommand
3624 args.json: boolean, if this flag is set to true, the output
3625 will be provided in json format for programmatic consumption
3626 @param session: the active session to use
3627 """
3628
3629 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003630
3631 data = {"data": args.DefaultGW}
3632
3633 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003634 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003635 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003636 except(requests.exceptions.Timeout):
3637 return(connectionErrHandler(args.json, "Timeout", None))
3638 except(requests.exceptions.ConnectionError) as err:
3639 return connectionErrHandler(args.json, "ConnectionError", err)
3640 if res.status_code == 403:
3641 return "Failed to set Default Gateway!!"
3642
3643 return res.text
3644
3645
3646def viewNWConfig(host, args, session):
3647 """
3648 Called by the ldap function. Prints out network configured properties
3649
3650 @param host: string, the hostname or IP address of the bmc
3651 @param args: contains additional arguments used by the ldap subcommand
3652 args.json: boolean, if this flag is set to true, the output
3653 will be provided in json format for programmatic consumption
3654 @param session: the active session to use
3655 @return returns LDAP's configured properties.
3656 """
3657 url = "https://"+host+"/xyz/openbmc_project/network/enumerate"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003658 try:
Justin Thaler27197622019-01-23 14:42:11 -06003659 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003660 except(requests.exceptions.Timeout):
3661 return(connectionErrHandler(args.json, "Timeout", None))
3662 except(requests.exceptions.ConnectionError) as err:
3663 return connectionErrHandler(args.json, "ConnectionError", err)
3664 except(requests.exceptions.RequestException) as err:
3665 return connectionErrHandler(args.json, "RequestException", err)
3666 if res.status_code == 404:
3667 return "LDAP server config has not been created"
3668 return res.text
3669
3670
3671def getDNS(host, args, session):
3672
3673 """
3674 Called by the network function. Prints out DNS servers on the interface
3675
3676 @param host: string, the hostname or IP address of the bmc
3677 @param args: contains additional arguments used by the ldap subcommand
3678 args.json: boolean, if this flag is set to true, the output
3679 will be provided in json format for programmatic consumption
3680 @param session: the active session to use
3681 """
3682
3683 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3684 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003685
3686 try:
Justin Thaler27197622019-01-23 14:42:11 -06003687 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003688 except(requests.exceptions.Timeout):
3689 return(connectionErrHandler(args.json, "Timeout", None))
3690 except(requests.exceptions.ConnectionError) as err:
3691 return connectionErrHandler(args.json, "ConnectionError", err)
3692 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003693 return "The NameServer is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003694
3695 return res.text
3696
3697
3698def setDNS(host, args, session):
3699 """
3700 Called by the network function. Sets DNS servers on the interface.
3701
3702 @param host: string, the hostname or IP address of the bmc
3703 @param args: contains additional arguments used by the ldap subcommand
3704 args.json: boolean, if this flag is set to true, the output
3705 will be provided in json format for programmatic consumption
3706 @param session: the active session to use
3707 """
3708
3709 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3710 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003711
3712 data = {"data": args.DNSServers.split(",")}
3713
3714 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003715 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003716 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003717 except(requests.exceptions.Timeout):
3718 return(connectionErrHandler(args.json, "Timeout", None))
3719 except(requests.exceptions.ConnectionError) as err:
3720 return connectionErrHandler(args.json, "ConnectionError", err)
3721 if res.status_code == 403:
3722 return "The specified Interface"+"("+args.Interface+")" +\
3723 " doesn't exist"
3724
3725 return res.text
3726
3727
3728def getNTP(host, args, session):
3729
3730 """
3731 Called by the network function. Prints out NTP servers on the interface
3732
3733 @param host: string, the hostname or IP address of the bmc
3734 @param args: contains additional arguments used by the ldap subcommand
3735 args.json: boolean, if this flag is set to true, the output
3736 will be provided in json format for programmatic consumption
3737 @param session: the active session to use
3738 """
3739
3740 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3741 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003742 try:
Justin Thaler27197622019-01-23 14:42:11 -06003743 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003744 except(requests.exceptions.Timeout):
3745 return(connectionErrHandler(args.json, "Timeout", None))
3746 except(requests.exceptions.ConnectionError) as err:
3747 return connectionErrHandler(args.json, "ConnectionError", err)
3748 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003749 return "The NTPServer is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003750
3751 return res.text
3752
3753
3754def setNTP(host, args, session):
3755 """
3756 Called by the network function. Sets NTP servers on the interface.
3757
3758 @param host: string, the hostname or IP address of the bmc
3759 @param args: contains additional arguments used by the ldap subcommand
3760 args.json: boolean, if this flag is set to true, the output
3761 will be provided in json format for programmatic consumption
3762 @param session: the active session to use
3763 """
3764
3765 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3766 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003767
3768 data = {"data": args.NTPServers.split(",")}
3769
3770 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003771 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003772 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003773 except(requests.exceptions.Timeout):
3774 return(connectionErrHandler(args.json, "Timeout", None))
3775 except(requests.exceptions.ConnectionError) as err:
3776 return connectionErrHandler(args.json, "ConnectionError", err)
3777 if res.status_code == 403:
3778 return "The specified Interface"+"("+args.Interface+")" +\
3779 " doesn't exist"
3780
3781 return res.text
3782
3783
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003784def addIP(host, args, session):
3785 """
3786 Called by the network function. Configures IP address on given 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 + "/action/IP"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003797 protocol = {
3798 'ipv4': 'xyz.openbmc_project.Network.IP.Protocol.IPv4',
3799 'ipv6': 'xyz.openbmc_project.Network.IP.Protocol.IPv6'
3800 }
3801
3802 data = {"data": [protocol[args.type], args.address, int(args.prefixLength),
3803 args.gateway]}
3804
3805 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003806 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003807 timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003808 except(requests.exceptions.Timeout):
3809 return(connectionErrHandler(args.json, "Timeout", None))
3810 except(requests.exceptions.ConnectionError) as err:
3811 return connectionErrHandler(args.json, "ConnectionError", err)
3812 if res.status_code == 404:
3813 return "The specified Interface" + "(" + args.Interface + ")" +\
3814 " doesn't exist"
3815
3816 return res.text
3817
3818
3819def getIP(host, args, session):
3820 """
3821 Called by the network function. Prints out IP address of given interface
3822
3823 @param host: string, the hostname or IP address of the bmc
3824 @param args: contains additional arguments used by the ldap subcommand
3825 args.json: boolean, if this flag is set to true, the output
3826 will be provided in json format for programmatic consumption
3827 @param session: the active session to use
3828 """
3829
3830 url = "https://" + host+"/xyz/openbmc_project/network/" + args.Interface +\
3831 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003832 try:
Justin Thaler27197622019-01-23 14:42:11 -06003833 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003834 except(requests.exceptions.Timeout):
3835 return(connectionErrHandler(args.json, "Timeout", None))
3836 except(requests.exceptions.ConnectionError) as err:
3837 return connectionErrHandler(args.json, "ConnectionError", err)
3838 if res.status_code == 404:
3839 return "The specified Interface" + "(" + args.Interface + ")" +\
3840 " doesn't exist"
3841
3842 return res.text
3843
3844
3845def deleteIP(host, args, session):
3846 """
3847 Called by the network function. Deletes the IP address from given Interface
3848
3849 @param host: string, the hostname or IP address of the bmc
3850 @param args: contains additional arguments used by the ldap subcommand
3851 @param session: the active session to use
3852 @param args.json: boolean, if this flag is set to true, the output
3853 will be provided in json format for programmatic consumption
3854 """
3855
3856 url = "https://"+host+"/xyz/openbmc_project/network/" + args.Interface+\
3857 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003858 data = {"data": []}
3859 try:
Justin Thaler27197622019-01-23 14:42:11 -06003860 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003861 except(requests.exceptions.Timeout):
3862 return(connectionErrHandler(args.json, "Timeout", None))
3863 except(requests.exceptions.ConnectionError) as err:
3864 return connectionErrHandler(args.json, "ConnectionError", err)
3865 if res.status_code == 404:
3866 return "The specified Interface" + "(" + args.Interface + ")" +\
3867 " doesn't exist"
3868 objDict = json.loads(res.text)
3869 if not objDict['data']:
3870 return "No object found for given address on given Interface"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003871 for obj in objDict['data']:
Sunitha Harish0baf6372019-07-31 03:59:03 -05003872 try:
3873 if args.address in objDict['data'][obj]['Address']:
3874 url = "https://"+host+obj+"/action/Delete"
3875 try:
3876 res = session.post(url, headers=jsonHeader, json=data,
3877 verify=False, timeout=baseTimeout)
3878 except(requests.exceptions.Timeout):
3879 return(connectionErrHandler(args.json, "Timeout", None))
3880 except(requests.exceptions.ConnectionError) as err:
3881 return connectionErrHandler(args.json, "ConnectionError", err)
3882 return res.text
3883 else:
3884 continue
3885 except KeyError:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003886 continue
3887 return "No object found for address " + args.address + \
3888 " on Interface(" + args.Interface + ")"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003889
3890
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003891def addVLAN(host, args, session):
3892 """
3893 Called by the network function. Creates VLAN on given interface.
3894
3895 @param host: string, the hostname or IP address of the bmc
3896 @param args: contains additional arguments used by the ldap subcommand
3897 args.json: boolean, if this flag is set to true, the output
3898 will be provided in json format for programmatic consumption
3899 @param session: the active session to use
3900 """
3901
3902 url = "https://" + host+"/xyz/openbmc_project/network/action/VLAN"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003903
Sunitha Harish0baf6372019-07-31 03:59:03 -05003904 data = {"data": [args.Interface,int(args.Identifier)]}
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003905 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003906 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003907 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003908 except(requests.exceptions.Timeout):
3909 return(connectionErrHandler(args.json, "Timeout", None))
3910 except(requests.exceptions.ConnectionError) as err:
3911 return connectionErrHandler(args.json, "ConnectionError", err)
3912 if res.status_code == 400:
Sunitha Harish0baf6372019-07-31 03:59:03 -05003913 return "Adding VLAN to interface" + "(" + args.Interface + ")" +\
3914 " failed"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003915
3916 return res.text
3917
3918
3919def deleteVLAN(host, args, session):
3920 """
3921 Called by the network function. Creates VLAN on given interface.
3922
3923 @param host: string, the hostname or IP address of the bmc
3924 @param args: contains additional arguments used by the ldap subcommand
3925 args.json: boolean, if this flag is set to true, the output
3926 will be provided in json format for programmatic consumption
3927 @param session: the active session to use
3928 """
3929
Sunitha Harish577a5032019-08-08 06:27:40 -05003930 url = "https://" + host+"/xyz/openbmc_project/network/"+args.Interface+"/action/Delete"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003931 data = {"data": []}
3932
3933 try:
Justin Thaler27197622019-01-23 14:42:11 -06003934 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003935 except(requests.exceptions.Timeout):
3936 return(connectionErrHandler(args.json, "Timeout", None))
3937 except(requests.exceptions.ConnectionError) as err:
3938 return connectionErrHandler(args.json, "ConnectionError", err)
3939 if res.status_code == 404:
Sunitha Harish577a5032019-08-08 06:27:40 -05003940 return "The specified VLAN"+"("+args.Interface+")" +" doesn't exist"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003941
3942 return res.text
3943
3944
3945def viewDHCPConfig(host, args, session):
3946 """
3947 Called by the network function. Shows DHCP configured Properties.
3948
3949 @param host: string, the hostname or IP address of the bmc
3950 @param args: contains additional arguments used by the ldap subcommand
3951 args.json: boolean, if this flag is set to true, the output
3952 will be provided in json format for programmatic consumption
3953 @param session: the active session to use
3954 """
3955
3956 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003957
3958 try:
Justin Thaler27197622019-01-23 14:42:11 -06003959 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003960 except(requests.exceptions.Timeout):
3961 return(connectionErrHandler(args.json, "Timeout", None))
3962 except(requests.exceptions.ConnectionError) as err:
3963 return connectionErrHandler(args.json, "ConnectionError", err)
3964
3965 return res.text
3966
3967
3968def configureDHCP(host, args, session):
3969 """
3970 Called by the network function. Configures/updates DHCP Properties.
3971
3972 @param host: string, the hostname or IP address of the bmc
3973 @param args: contains additional arguments used by the ldap subcommand
3974 args.json: boolean, if this flag is set to true, the output
3975 will be provided in json format for programmatic consumption
3976 @param session: the active session to use
3977 """
3978
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003979
3980 try:
3981 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
3982 if(args.DNSEnabled == True):
3983 data = '{"data": 1}'
3984 else:
3985 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06003986 res = session.put(url + '/attr/DNSEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06003987 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003988 if(args.HostNameEnabled == True):
3989 data = '{"data": 1}'
3990 else:
3991 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06003992 res = session.put(url + '/attr/HostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06003993 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003994 if(args.NTPEnabled == True):
3995 data = '{"data": 1}'
3996 else:
3997 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06003998 res = session.put(url + '/attr/NTPEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06003999 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004000 if(args.SendHostNameEnabled == True):
4001 data = '{"data": 1}'
4002 else:
4003 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004004 res = session.put(url + '/attr/SendHostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004005 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004006 except(requests.exceptions.Timeout):
4007 return(connectionErrHandler(args.json, "Timeout", None))
4008 except(requests.exceptions.ConnectionError) as err:
4009 return connectionErrHandler(args.json, "ConnectionError", err)
4010
4011 return res.text
4012
4013
4014def nwReset(host, args, session):
4015
4016 """
4017 Called by the network function. Resets networks setting to factory defaults.
4018
4019 @param host: string, the hostname or IP address of the bmc
4020 @param args: contains additional arguments used by the ldap subcommand
4021 args.json: boolean, if this flag is set to true, the output
4022 will be provided in json format for programmatic consumption
4023 @param session: the active session to use
4024 """
4025
4026 url = "https://"+host+"/xyz/openbmc_project/network/action/Reset"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004027 data = '{"data":[] }'
4028 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06004029 res = session.post(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004030 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004031
4032 except(requests.exceptions.Timeout):
4033 return(connectionErrHandler(args.json, "Timeout", None))
4034 except(requests.exceptions.ConnectionError) as err:
4035 return connectionErrHandler(args.json, "ConnectionError", err)
4036
4037 return res.text
4038
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004039def getLDAPTypeEnabled(host,session):
4040
4041 """
4042 Called by LDAP related functions to find the LDAP server type that has been enabled.
4043 Returns None if LDAP has not been configured.
4044
4045 @param host: string, the hostname or IP address of the bmc
4046 @param session: the active session to use
4047 """
4048
4049 enabled = False
4050 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
4051 for key,value in serverTypeMap.items():
4052 data = {"data": []}
4053 try:
4054 res = session.get(url + value + '/attr/Enabled', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4055 except(requests.exceptions.Timeout):
4056 print(connectionErrHandler(args.json, "Timeout", None))
4057 return
4058 except(requests.exceptions.ConnectionError) as err:
4059 print(connectionErrHandler(args.json, "ConnectionError", err))
4060 return
4061
4062 enabled = res.json()['data']
4063 if (enabled):
4064 return key
4065
4066def syncRoleMap(host,args,session,fromServerType,toServerType):
4067
4068 """
4069 Called by LDAP related functions to sync the role maps
4070 Returns False if LDAP has not been configured.
4071
4072 @param host: string, the hostname or IP address of the bmc
4073 @param session: the active session to use
4074 @param fromServerType : Server type whose role map has to be copied
4075 @param toServerType : Server type to which role map has to be copied
4076 """
4077
4078 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
4079
4080 try:
4081 #Note: If the fromServerType has no role map, then
4082 #the toServerType will not have any role map.
4083
4084 #delete the privilege mapping from the toServerType and
4085 #then copy the privilege mapping from fromServerType to
4086 #toServerType.
4087 args.serverType = toServerType
4088 res = deleteAllPrivilegeMapping(host, args, session)
4089
4090 data = {"data": []}
4091 res = session.get(url + serverTypeMap[fromServerType] + '/role_map/enumerate', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4092 #Previously enabled server type has no role map
4093 if (res.status_code != requests.codes.ok):
4094
4095 #fromServerType has no role map; So, no need to copy
4096 #role map to toServerType.
4097 return
4098
4099 objDict = json.loads(res.text)
4100 dataDict = objDict['data']
4101 for key,value in dataDict.items():
4102 data = {"data": [value["GroupName"], value["Privilege"]]}
4103 res = session.post(url + serverTypeMap[toServerType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4104
4105 except(requests.exceptions.Timeout):
4106 return(connectionErrHandler(args.json, "Timeout", None))
4107 except(requests.exceptions.ConnectionError) as err:
4108 return connectionErrHandler(args.json, "ConnectionError", err)
4109 return res.text
4110
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004111
Ratan Guptafeee6372018-10-17 23:25:51 +05304112def createPrivilegeMapping(host, args, session):
4113 """
4114 Called by the ldap function. Creates the group and the privilege mapping.
4115
4116 @param host: string, the hostname or IP address of the bmc
4117 @param args: contains additional arguments used by the ldap subcommand
4118 @param session: the active session to use
4119 @param args.json: boolean, if this flag is set to true, the output
4120 will be provided in json format for programmatic consumption
4121 """
4122
Ratan Guptafeee6372018-10-17 23:25:51 +05304123 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004124 if (isRedfishSupport):
4125 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
4126
4127 #To maintain the interface compatibility between op930 and op940, the server type has been made
4128 #optional. If the server type is not specified, then create the role-mapper for the currently
4129 #enabled server type.
4130 serverType = args.serverType
4131 if (serverType is None):
4132 serverType = getLDAPTypeEnabled(host,session)
4133 if (serverType is None):
4134 return("LDAP server has not been enabled. Please specify LDAP serverType to proceed further...")
4135
4136 data = {"data": [args.groupName,args.privilege]}
4137 res = session.post(url + serverTypeMap[serverType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4138
4139 else:
4140 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/action/Create'
4141 data = {"data": [args.groupName,args.privilege]}
4142 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4143
Ratan Guptafeee6372018-10-17 23:25:51 +05304144 except(requests.exceptions.Timeout):
4145 return(connectionErrHandler(args.json, "Timeout", None))
4146 except(requests.exceptions.ConnectionError) as err:
4147 return connectionErrHandler(args.json, "ConnectionError", err)
4148 return res.text
4149
4150def listPrivilegeMapping(host, args, session):
4151 """
4152 Called by the ldap function. Lists the group and the privilege mapping.
4153
4154 @param host: string, the hostname or IP address of the bmc
4155 @param args: contains additional arguments used by the ldap subcommand
4156 @param session: the active session to use
4157 @param args.json: boolean, if this flag is set to true, the output
4158 will be provided in json format for programmatic consumption
4159 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004160
4161 if (isRedfishSupport):
4162 serverType = args.serverType
4163 if (serverType is None):
4164 serverType = getLDAPTypeEnabled(host,session)
4165 if (serverType is None):
4166 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4167
4168 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'+serverTypeMap[serverType]+'/role_map/enumerate'
4169
4170 else:
4171 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/enumerate'
4172
Ratan Guptafeee6372018-10-17 23:25:51 +05304173 data = {"data": []}
4174
4175 try:
Justin Thaler27197622019-01-23 14:42:11 -06004176 res = session.get(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05304177 except(requests.exceptions.Timeout):
4178 return(connectionErrHandler(args.json, "Timeout", None))
4179 except(requests.exceptions.ConnectionError) as err:
4180 return connectionErrHandler(args.json, "ConnectionError", err)
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004181
Ratan Guptafeee6372018-10-17 23:25:51 +05304182 return res.text
4183
4184def deletePrivilegeMapping(host, args, session):
4185 """
4186 Called by the ldap function. Deletes the mapping associated with the group.
4187
4188 @param host: string, the hostname or IP address of the bmc
4189 @param args: contains additional arguments used by the ldap subcommand
4190 @param session: the active session to use
4191 @param args.json: boolean, if this flag is set to true, the output
4192 will be provided in json format for programmatic consumption
4193 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004194
4195 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
Ratan Guptafeee6372018-10-17 23:25:51 +05304196 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
4197 path = ''
Ratan Guptafeee6372018-10-17 23:25:51 +05304198 data = {"data": []}
4199
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004200 if (isRedfishSupport):
4201 if (args.serverType is None):
4202 serverType = getLDAPTypeEnabled(host,session)
4203 if (serverType is None):
4204 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4205 # search for the object having the mapping for the given group
4206 for key,value in ldapNameSpaceObjects.items():
4207 if value['GroupName'] == args.groupName:
4208 path = key
4209 break
4210
4211 if path == '':
4212 return "No privilege mapping found for this group."
4213
4214 # delete the object
4215 url = 'https://'+host+path+'/action/Delete'
4216
4217 else:
4218 # not interested in the config objet
4219 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
4220
4221 # search for the object having the mapping for the given group
4222 for key,value in ldapNameSpaceObjects.items():
4223 if value['GroupName'] == args.groupName:
4224 path = key
4225 break
4226
4227 if path == '':
4228 return "No privilege mapping found for this group."
4229
4230 # delete the object
4231 url = 'https://'+host+path+'/action/delete'
4232
Ratan Guptafeee6372018-10-17 23:25:51 +05304233 try:
Justin Thaler27197622019-01-23 14:42:11 -06004234 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05304235 except(requests.exceptions.Timeout):
4236 return(connectionErrHandler(args.json, "Timeout", None))
4237 except(requests.exceptions.ConnectionError) as err:
4238 return connectionErrHandler(args.json, "ConnectionError", err)
4239 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05304240
Sivas SRR78835272018-11-27 05:27:19 -06004241def deleteAllPrivilegeMapping(host, args, session):
4242 """
4243 Called by the ldap function. Deletes all the privilege mapping and group defined.
4244 @param host: string, the hostname or IP address of the bmc
4245 @param args: contains additional arguments used by the ldap subcommand
4246 @param session: the active session to use
4247 @param args.json: boolean, if this flag is set to true, the output
4248 will be provided in json format for programmatic consumption
4249 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004250
Sivas SRR78835272018-11-27 05:27:19 -06004251 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
4252 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
4253 path = ''
Sivas SRR78835272018-11-27 05:27:19 -06004254 data = {"data": []}
4255
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004256 if (isRedfishSupport):
4257 if (args.serverType is None):
4258 serverType = getLDAPTypeEnabled(host,session)
4259 if (serverType is None):
4260 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4261
4262 else:
4263 # Remove the config object.
4264 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
4265
Sivas SRR78835272018-11-27 05:27:19 -06004266 try:
4267 # search for GroupName property and delete if it is available.
4268 for path in ldapNameSpaceObjects.keys():
4269 # delete the object
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004270 url = 'https://'+host+path+'/action/Delete'
Justin Thaler27197622019-01-23 14:42:11 -06004271 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004272
Sivas SRR78835272018-11-27 05:27:19 -06004273 except(requests.exceptions.Timeout):
4274 return(connectionErrHandler(args.json, "Timeout", None))
4275 except(requests.exceptions.ConnectionError) as err:
4276 return connectionErrHandler(args.json, "ConnectionError", err)
4277 return res.text
4278
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004279def viewLDAPConfig(host, args, session):
4280 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004281 Called by the ldap function. Prints out active LDAP configuration properties
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004282
4283 @param host: string, the hostname or IP address of the bmc
4284 @param args: contains additional arguments used by the ldap subcommand
4285 args.json: boolean, if this flag is set to true, the output
4286 will be provided in json format for programmatic consumption
4287 @param session: the active session to use
4288 @return returns LDAP's configured properties.
4289 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004290
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004291 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004292 if (isRedfishSupport):
4293
4294 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
4295
4296 serverTypeEnabled = getLDAPTypeEnabled(host,session)
4297
4298 if (serverTypeEnabled is not None):
4299 data = {"data": []}
4300 res = session.get(url + serverTypeMap[serverTypeEnabled], headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4301 else:
4302 return("LDAP server has not been enabled...")
4303
4304 else :
4305 url = "https://"+host+"/xyz/openbmc_project/user/ldap/config"
4306 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
4307
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004308 except(requests.exceptions.Timeout):
4309 return(connectionErrHandler(args.json, "Timeout", None))
4310 except(requests.exceptions.ConnectionError) as err:
4311 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004312 if res.status_code == 404:
4313 return "LDAP server config has not been created"
4314 return res.text
4315
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004316def str2bool(v):
4317 if v.lower() in ('yes', 'true', 't', 'y', '1'):
4318 return True
4319 elif v.lower() in ('no', 'false', 'f', 'n', '0'):
4320 return False
4321 else:
4322 raise argparse.ArgumentTypeError('Boolean value expected.')
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004323
Matt Spinler7d426c22018-09-24 14:42:07 -05004324def localUsers(host, args, session):
4325 """
4326 Enables and disables local BMC users.
4327
4328 @param host: string, the hostname or IP address of the bmc
4329 @param args: contains additional arguments used by the logging sub command
4330 @param session: the active session to use
4331 """
4332
Matt Spinler7d426c22018-09-24 14:42:07 -05004333 url="https://{hostname}/xyz/openbmc_project/user/enumerate".format(hostname=host)
4334 try:
Justin Thaler27197622019-01-23 14:42:11 -06004335 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004336 except(requests.exceptions.Timeout):
4337 return(connectionErrHandler(args.json, "Timeout", None))
4338 usersDict = json.loads(res.text)
4339
4340 if not usersDict['data']:
4341 return "No users found"
4342
4343 output = ""
4344 for user in usersDict['data']:
Matt Spinler015adc22018-10-23 14:30:19 -05004345
4346 # Skip LDAP and another non-local users
4347 if 'UserEnabled' not in usersDict['data'][user]:
4348 continue
4349
Matt Spinler7d426c22018-09-24 14:42:07 -05004350 name = user.split('/')[-1]
4351 url = "https://{hostname}{user}/attr/UserEnabled".format(hostname=host, user=user)
4352
4353 if args.local_users == "queryenabled":
4354 try:
Justin Thaler27197622019-01-23 14:42:11 -06004355 res = session.get(url, headers=jsonHeader,verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004356 except(requests.exceptions.Timeout):
4357 return(connectionErrHandler(args.json, "Timeout", None))
4358
4359 result = json.loads(res.text)
4360 output += ("User: {name} Enabled: {result}\n").format(name=name, result=result['data'])
4361
4362 elif args.local_users in ["enableall", "disableall"]:
4363 action = ""
4364 if args.local_users == "enableall":
4365 data = '{"data": true}'
4366 action = "Enabling"
4367 else:
4368 data = '{"data": false}'
4369 action = "Disabling"
4370
4371 output += "{action} {name}\n".format(action=action, name=name)
4372
4373 try:
Justin Thaler27197622019-01-23 14:42:11 -06004374 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004375 except(requests.exceptions.Timeout):
4376 return connectionErrHandler(args.json, "Timeout", None)
4377 except(requests.exceptions.ConnectionError) as err:
4378 return connectionErrHandler(args.json, "ConnectionError", err)
4379 else:
4380 return "Invalid local users argument"
4381
4382 return output
4383
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004384def setPassword(host, args, session):
4385 """
4386 Set local user password
4387 @param host: string, the hostname or IP address of the bmc
4388 @param args: contains additional arguments used by the logging sub
4389 command
4390 @param session: the active session to use
4391 @param args.json: boolean, if this flag is set to true, the output
4392 will be provided in json format for programmatic consumption
4393 @return: Session object
4394 """
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004395 try:
Sunitha Harishc99faba2019-07-19 06:55:22 -05004396 if(isRedfishSupport):
4397 url = "https://" + host + "/redfish/v1/AccountService/Accounts/"+ \
4398 args.user
4399 data = {"Password":args.password}
4400 res = session.patch(url, headers=jsonHeader, json=data,
4401 verify=False, timeout=baseTimeout)
4402 else:
4403 url = "https://" + host + "/xyz/openbmc_project/user/" + args.user + \
4404 "/action/SetPassword"
4405 res = session.post(url, headers=jsonHeader,
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004406 json={"data": [args.password]}, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004407 timeout=baseTimeout)
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004408 except(requests.exceptions.Timeout):
4409 return(connectionErrHandler(args.json, "Timeout", None))
4410 except(requests.exceptions.ConnectionError) as err:
4411 return connectionErrHandler(args.json, "ConnectionError", err)
4412 except(requests.exceptions.RequestException) as err:
4413 return connectionErrHandler(args.json, "RequestException", err)
Sunitha Harishc99faba2019-07-19 06:55:22 -05004414 return res.status_code
Matthew Barth368e83c2019-02-01 13:48:25 -06004415
4416def getThermalZones(host, args, session):
4417 """
4418 Get the available thermal control zones
4419 @param host: string, the hostname or IP address of the bmc
4420 @param args: contains additional arguments used to get the thermal
4421 control zones
4422 @param session: the active session to use
4423 @return: Session object
4424 """
4425 url = "https://" + host + "/xyz/openbmc_project/control/thermal/enumerate"
4426
4427 try:
4428 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4429 except(requests.exceptions.Timeout):
4430 return(connectionErrHandler(args.json, "Timeout", None))
4431 except(requests.exceptions.ConnectionError) as err:
4432 return connectionErrHandler(args.json, "ConnectionError", err)
4433 except(requests.exceptions.RequestException) as err:
4434 return connectionErrHandler(args.json, "RequestException", err)
4435
4436 if (res.status_code == 404):
Matthew Barth0939e822019-09-27 15:47:50 -05004437 return "No thermal control zones found"
Matthew Barth368e83c2019-02-01 13:48:25 -06004438
4439 zonesDict = json.loads(res.text)
4440 if not zonesDict['data']:
4441 return "No thermal control zones found"
4442 for zone in zonesDict['data']:
4443 z = ",".join(str(zone.split('/')[-1]) for zone in zonesDict['data'])
4444
4445 return "Zones: [ " + z + " ]"
4446
4447
4448def getThermalMode(host, args, session):
4449 """
4450 Get thermal control mode
4451 @param host: string, the hostname or IP address of the bmc
4452 @param args: contains additional arguments used to get the thermal
4453 control mode
4454 @param session: the active session to use
4455 @param args.zone: the zone to get the mode on
4456 @return: Session object
4457 """
4458 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
4459 args.zone
4460
4461 try:
4462 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4463 except(requests.exceptions.Timeout):
4464 return(connectionErrHandler(args.json, "Timeout", None))
4465 except(requests.exceptions.ConnectionError) as err:
4466 return connectionErrHandler(args.json, "ConnectionError", err)
4467 except(requests.exceptions.RequestException) as err:
4468 return connectionErrHandler(args.json, "RequestException", err)
4469
4470 if (res.status_code == 404):
Matthew Barth0939e822019-09-27 15:47:50 -05004471 return "Thermal control zone(" + args.zone + ") not found"
Matthew Barth368e83c2019-02-01 13:48:25 -06004472
4473 propsDict = json.loads(res.text)
4474 if not propsDict['data']:
4475 return "No thermal control properties found on zone(" + args.zone + ")"
4476 curMode = "Current"
4477 supModes = "Supported"
4478 result = "\n"
4479 for prop in propsDict['data']:
4480 if (prop.casefold() == curMode.casefold()):
4481 result += curMode + " Mode: " + propsDict['data'][curMode] + "\n"
4482 if (prop.casefold() == supModes.casefold()):
4483 s = ", ".join(str(sup) for sup in propsDict['data'][supModes])
4484 result += supModes + " Modes: [ " + s + " ]\n"
4485
4486 return result
4487
4488def setThermalMode(host, args, session):
4489 """
4490 Set thermal control mode
4491 @param host: string, the hostname or IP address of the bmc
4492 @param args: contains additional arguments used for setting the thermal
4493 control mode
4494 @param session: the active session to use
4495 @param args.zone: the zone to set the mode on
4496 @param args.mode: the mode to enable
4497 @return: Session object
4498 """
4499 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
4500 args.zone + "/attr/Current"
4501
4502 # Check args.mode against supported modes using `getThermalMode` output
4503 modes = getThermalMode(host, args, session)
4504 modes = os.linesep.join([m for m in modes.splitlines() if m])
4505 modes = modes.replace("\n", ";").strip()
4506 modesDict = dict(m.split(': ') for m in modes.split(';'))
4507 sModes = ''.join(s for s in modesDict['Supported Modes'] if s not in '[ ]')
4508 if args.mode.casefold() not in \
4509 (m.casefold() for m in sModes.split(',')) or not args.mode:
4510 result = ("Unsupported mode('" + args.mode + "') given, " +
4511 "select a supported mode: \n" +
4512 getThermalMode(host, args, session))
4513 return result
4514
4515 data = '{"data":"' + args.mode + '"}'
4516 try:
4517 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4518 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)
4524
4525 if (data and res.status_code != 404):
4526 try:
4527 res = session.put(url, headers=jsonHeader,
4528 data=data, verify=False,
4529 timeout=30)
4530 except(requests.exceptions.Timeout):
4531 return(connectionErrHandler(args.json, "Timeout", None))
4532 except(requests.exceptions.ConnectionError) as err:
4533 return connectionErrHandler(args.json, "ConnectionError", err)
4534 except(requests.exceptions.RequestException) as err:
4535 return connectionErrHandler(args.json, "RequestException", err)
4536
4537 if res.status_code == 403:
4538 return "The specified thermal control zone(" + args.zone + ")" + \
4539 " does not exist"
4540
4541 return res.text
4542 else:
4543 return "Setting thermal control mode(" + args.mode + ")" + \
Matthew Barth0939e822019-09-27 15:47:50 -05004544 " not supported or operation not available"
Matthew Barth368e83c2019-02-01 13:48:25 -06004545
4546
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004547def createCommandParser():
Justin Thalere412dc22018-01-12 16:28:24 -06004548 """
4549 creates the parser for the command line along with help for each command and subcommand
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004550
Justin Thalere412dc22018-01-12 16:28:24 -06004551 @return: returns the parser for the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004552 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004553 parser = argparse.ArgumentParser(description='Process arguments')
Justin Thalere412dc22018-01-12 16:28:24 -06004554 parser.add_argument("-H", "--host", help='A hostname or IP for the BMC')
4555 parser.add_argument("-U", "--user", help='The username to login with')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004556 group = parser.add_mutually_exclusive_group()
4557 group.add_argument("-A", "--askpw", action='store_true', help='prompt for password')
4558 group.add_argument("-P", "--PW", help='Provide the password in-line')
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05004559 group.add_argument("-E", "--PWenvvar", action='store_true', help='Get password from envvar OPENBMCTOOL_PASSWORD')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004560 parser.add_argument('-j', '--json', action='store_true', help='output json data only')
4561 parser.add_argument('-t', '--policyTableLoc', help='The location of the policy table to parse alerts')
4562 parser.add_argument('-c', '--CerFormat', action='store_true', help=argparse.SUPPRESS)
4563 parser.add_argument('-T', '--procTime', action='store_true', help= argparse.SUPPRESS)
Justin Thalere412dc22018-01-12 16:28:24 -06004564 parser.add_argument('-V', '--version', action='store_true', help='Display the version number of the openbmctool')
4565 subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004566
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004567 #fru command
4568 parser_inv = subparsers.add_parser("fru", help='Work with platform inventory')
Justin Thalere412dc22018-01-12 16:28:24 -06004569 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 -05004570 inv_subparser.required = True
4571 #fru print
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004572 inv_print = inv_subparser.add_parser("print", help="prints out a list of all FRUs")
4573 inv_print.set_defaults(func=fruPrint)
4574 #fru list [0....n]
4575 inv_list = inv_subparser.add_parser("list", help="print out details on selected FRUs. Specifying no items will list the entire inventory")
4576 inv_list.add_argument('items', nargs='?', help="print out details on selected FRUs. Specifying no items will list the entire inventory")
4577 inv_list.set_defaults(func=fruList)
4578 #fru status
4579 inv_status = inv_subparser.add_parser("status", help="prints out the status of all FRUs")
Justin Thalere412dc22018-01-12 16:28:24 -06004580 inv_status.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004581 inv_status.set_defaults(func=fruStatus)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004582
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004583 #sensors command
4584 parser_sens = subparsers.add_parser("sensors", help="Work with platform sensors")
Justin Thalere412dc22018-01-12 16:28:24 -06004585 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 -05004586 sens_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004587 #sensor print
4588 sens_print= sens_subparser.add_parser('print', help="prints out a list of all Sensors.")
4589 sens_print.set_defaults(func=sensor)
4590 #sensor list[0...n]
4591 sens_list=sens_subparser.add_parser("list", help="Lists all Sensors in the platform. Specify a sensor for full details. ")
4592 sens_list.add_argument("sensNum", nargs='?', help="The Sensor number to get full details on" )
4593 sens_list.set_defaults(func=sensor)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004594
Matthew Barth368e83c2019-02-01 13:48:25 -06004595 #thermal control commands
4596 parser_therm = subparsers.add_parser("thermal", help="Work with thermal control parameters")
4597 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')
4598 #thermal control zones
4599 parser_thermZones = therm_subparser.add_parser("zones", help="Get a list of available thermal control zones")
4600 parser_thermZones.set_defaults(func=getThermalZones)
4601 #thermal control modes
4602 parser_thermMode = therm_subparser.add_parser("modes", help="Work with thermal control modes")
4603 thermMode_sub = parser_thermMode.add_subparsers(title='subactions', description='Work with thermal control modes', help="Work with thermal control modes")
4604 #get thermal control mode
4605 parser_getThermMode = thermMode_sub.add_parser("get", help="Get current and supported thermal control modes")
4606 parser_getThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
4607 parser_getThermMode.set_defaults(func=getThermalMode)
4608 #set thermal control mode
4609 parser_setThermMode = thermMode_sub.add_parser("set", help="Set the thermal control mode")
4610 parser_setThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
4611 parser_setThermMode.add_argument('-m', '--mode', required=True, help='The supported thermal control mode')
4612 parser_setThermMode.set_defaults(func=setThermalMode)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004613
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004614 #sel command
4615 parser_sel = subparsers.add_parser("sel", help="Work with platform alerts")
Justin Thalere412dc22018-01-12 16:28:24 -06004616 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 -05004617 sel_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004618 #sel print
4619 sel_print = sel_subparser.add_parser("print", help="prints out a list of all sels in a condensed list")
4620 sel_print.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
4621 sel_print.add_argument('-v', '--verbose', action='store_true', help="Changes the output to being very verbose")
4622 sel_print.add_argument('-f', '--fileloc', help='Parse a file instead of the BMC output')
4623 sel_print.set_defaults(func=selPrint)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004624
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004625 #sel list
4626 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")
4627 sel_list.add_argument("selNum", nargs='?', type=int, help="The SEL entry to get details on")
4628 sel_list.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004629
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004630 sel_get = sel_subparser.add_parser("get", help="Gets the verbose details of a specified SEL entry")
4631 sel_get.add_argument('selNum', type=int, help="the number of the SEL entry to get")
4632 sel_get.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004633
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004634 sel_clear = sel_subparser.add_parser("clear", help="Clears all entries from the SEL")
4635 sel_clear.set_defaults(func=selClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004636
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004637 sel_setResolved = sel_subparser.add_parser("resolve", help="Sets the sel entry to resolved")
Justin Thalere412dc22018-01-12 16:28:24 -06004638 sel_setResolved.add_argument('-n', '--selNum', type=int, help="the number of the SEL entry to resolve")
4639 sel_ResolveAll_sub = sel_setResolved.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
4640 sel_ResolveAll = sel_ResolveAll_sub.add_parser('all', help='Resolve all SEL entries')
4641 sel_ResolveAll.set_defaults(func=selResolveAll)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004642 sel_setResolved.set_defaults(func=selSetResolved)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004643
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004644 parser_chassis = subparsers.add_parser("chassis", help="Work with chassis power and status")
Justin Thalere412dc22018-01-12 16:28:24 -06004645 chas_sub = parser_chassis.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004646
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004647 parser_chassis.add_argument('status', action='store_true', help='Returns the current status of the platform')
4648 parser_chassis.set_defaults(func=chassis)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004649
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004650 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 -06004651 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 -06004652 parser_chasPower.set_defaults(func=chassisPower)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004653
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004654 #control the chassis identify led
4655 parser_chasIdent = chas_sub.add_parser("identify", help="Control the chassis identify led")
4656 parser_chasIdent.add_argument('identcmd', choices=['on', 'off', 'status'], help='The control option for the led: on, off, blink, status')
4657 parser_chasIdent.set_defaults(func=chassisIdent)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004658
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004659 #collect service data
4660 parser_servData = subparsers.add_parser("collect_service_data", help="Collect all bmc data needed for service")
4661 parser_servData.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
4662 parser_servData.set_defaults(func=collectServiceData)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004663
Justin Thalere412dc22018-01-12 16:28:24 -06004664 #system quick health check
4665 parser_healthChk = subparsers.add_parser("health_check", help="Work with platform sensors")
4666 parser_healthChk.set_defaults(func=healthCheck)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004667
Ravi Tejad8be0b42020-03-18 14:31:46 -05004668 #work with dumps
4669 parser_bmcdump = subparsers.add_parser("dump", help="Work with dumps")
4670 parser_bmcdump.add_argument("-t", "--dumpType", default='bmc', choices=['bmc','SystemDump'],help="Type of dump")
Justin Thalere412dc22018-01-12 16:28:24 -06004671 bmcDump_sub = parser_bmcdump.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thaler53bf2f12018-07-16 14:05:32 -05004672 bmcDump_sub.required = True
Ravi Tejad8be0b42020-03-18 14:31:46 -05004673 dump_Create = bmcDump_sub.add_parser('create', help="Create a dump of given type")
4674 dump_Create.set_defaults(func=dumpCreate)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004675
Ravi Tejad8be0b42020-03-18 14:31:46 -05004676 dump_list = bmcDump_sub.add_parser('list', help="list all dumps")
4677 dump_list.set_defaults(func=dumpList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004678
Ravi Tejad8be0b42020-03-18 14:31:46 -05004679 parserdumpdelete = bmcDump_sub.add_parser('delete', help="Delete dump")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004680 parserdumpdelete.add_argument("-n", "--dumpNum", nargs='*', type=int, help="The Dump entry to delete")
Ravi Tejad8be0b42020-03-18 14:31:46 -05004681 parserdumpdelete.set_defaults(func=dumpDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004682
Justin Thalere412dc22018-01-12 16:28:24 -06004683 bmcDumpDelsub = parserdumpdelete.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Ravi Tejad8be0b42020-03-18 14:31:46 -05004684 deleteAllDumps = bmcDumpDelsub.add_parser('all', help='Delete all dumps')
4685 deleteAllDumps.set_defaults(func=dumpDeleteAll)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004686
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004687 parser_dumpretrieve = bmcDump_sub.add_parser('retrieve', help='Retrieve a dump file')
Ravi Tejad8be0b42020-03-18 14:31:46 -05004688 parser_dumpretrieve.add_argument("-n,", "--dumpNum", help="The Dump entry to retrieve")
4689 parser_dumpretrieve.add_argument("-s", "--dumpSaveLoc", help="The location to save the bmc dump file or file path for system dump")
4690 parser_dumpretrieve.set_defaults(func=dumpRetrieve)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004691
Justin Thaler22b1bb52018-03-15 13:31:32 -05004692 #bmc command for reseting the bmc
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004693 parser_bmc = subparsers.add_parser('bmc', help="Work with the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004694 bmc_sub = parser_bmc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004695 parser_BMCReset = bmc_sub.add_parser('reset', help='Reset the bmc' )
4696 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 -06004697 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.")
4698 parser_bmc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004699
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004700 #add alias to the bmc command
4701 parser_mc = subparsers.add_parser('mc', help="Work with the management controller")
Justin Thalere412dc22018-01-12 16:28:24 -06004702 mc_sub = parser_mc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004703 parser_MCReset = mc_sub.add_parser('reset', help='Reset the bmc' )
4704 parser_MCReset.add_argument('type', choices=['warm','cold'], help="Reboot the BMC")
4705 #parser_MCReset.add_argument('cold', action='store_true', help="Reboot the BMC and CLEAR the configuration")
4706 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 -06004707 parser_MCReset.set_defaults(func=bmcReset)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004708 parser_mc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004709
Justin Thalere412dc22018-01-12 16:28:24 -06004710 #gard clear
4711 parser_gc = subparsers.add_parser("gardclear", help="Used to clear gard records")
4712 parser_gc.set_defaults(func=gardClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004713
Justin Thalere412dc22018-01-12 16:28:24 -06004714 #firmware_flash
4715 parser_fw = subparsers.add_parser("firmware", help="Work with the system firmware")
4716 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 -05004717 fwflash_subproc.required = True
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004718
Justin Thalere412dc22018-01-12 16:28:24 -06004719 fwflash = fwflash_subproc.add_parser('flash', help="Flash the system firmware")
4720 fwflash.add_argument('type', choices=['bmc', 'pnor'], help="image type to flash")
4721 fwflash.add_argument('-f', '--fileloc', required=True, help="The absolute path to the firmware image")
4722 fwflash.set_defaults(func=fwFlash)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004723
Justin Thaler22b1bb52018-03-15 13:31:32 -05004724 fwActivate = fwflash_subproc.add_parser('activate', help="Activate existing image on the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004725 fwActivate.add_argument('imageID', help="The image ID to activate from the firmware list. Ex: 63c95399")
4726 fwActivate.set_defaults(func=activateFWImage)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004727
Justin Thaler22b1bb52018-03-15 13:31:32 -05004728 fwActivateStatus = fwflash_subproc.add_parser('activation_status', help="Check Status of activations")
4729 fwActivateStatus.set_defaults(func=activateStatus)
4730
Justin Thaler3d71d402018-07-24 14:35:39 -05004731 fwList = fwflash_subproc.add_parser('list', help="List all of the installed firmware")
4732 fwList.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4733 fwList.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004734
Justin Thaler3d71d402018-07-24 14:35:39 -05004735 fwprint = fwflash_subproc.add_parser('print', help="List all of the installed firmware")
4736 fwprint.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4737 fwprint.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004738
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06004739 fwDelete = fwflash_subproc.add_parser('delete', help="Delete an existing firmware version")
4740 fwDelete.add_argument('versionID', help="The version ID to delete from the firmware list. Ex: 63c95399")
4741 fwDelete.set_defaults(func=deleteFWVersion)
4742
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004743 #logging
4744 parser_logging = subparsers.add_parser("logging", help="logging controls")
4745 logging_sub = parser_logging.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004746
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004747 #turn rest api logging on/off
4748 parser_rest_logging = logging_sub.add_parser("rest_api", help="turn rest api logging on/off")
4749 parser_rest_logging.add_argument('rest_logging', choices=['on', 'off'], help='The control option for rest logging: on, off')
4750 parser_rest_logging.set_defaults(func=restLogging)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05004751
4752 #remote logging
4753 parser_remote_logging = logging_sub.add_parser("remote_logging", help="Remote logging (rsyslog) commands")
4754 parser_remote_logging.add_argument('remote_logging', choices=['view', 'disable'], help='Remote logging (rsyslog) commands')
4755 parser_remote_logging.set_defaults(func=remoteLogging)
4756
4757 #configure remote logging
4758 parser_remote_logging_config = logging_sub.add_parser("remote_logging_config", help="Configure remote logging (rsyslog)")
4759 parser_remote_logging_config.add_argument("-a", "--address", required=True, help="Set IP address of rsyslog server")
4760 parser_remote_logging_config.add_argument("-p", "--port", required=True, type=int, help="Set Port of rsyslog server")
4761 parser_remote_logging_config.set_defaults(func=remoteLoggingConfig)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05004762
4763 #certificate management
4764 parser_cert = subparsers.add_parser("certificate", help="Certificate management")
4765 certMgmt_subproc = parser_cert.add_subparsers(title='subcommands', description='valid certificate commands', help='sub-command help', dest='command')
4766
4767 certUpdate = certMgmt_subproc.add_parser('update', help="Update the certificate")
4768 certUpdate.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to update")
4769 certUpdate.add_argument('service', choices=['https', 'ldap'], help="Service to update")
4770 certUpdate.add_argument('-f', '--fileloc', required=True, help="The absolute path to the certificate file")
4771 certUpdate.set_defaults(func=certificateUpdate)
4772
4773 certDelete = certMgmt_subproc.add_parser('delete', help="Delete the certificate")
4774 certDelete.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to delete")
4775 certDelete.add_argument('service', choices=['https', 'ldap'], help="Service to delete the certificate")
4776 certDelete.set_defaults(func=certificateDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004777
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05004778 certReplace = certMgmt_subproc.add_parser('replace',
4779 help="Replace the certificate")
4780 certReplace.add_argument('type', choices=['server', 'client', 'authority'],
4781 help="certificate type to replace")
4782 certReplace.add_argument('service', choices=['https', 'ldap'],
4783 help="Service to replace the certificate")
4784 certReplace.add_argument('-f', '--fileloc', required=True,
4785 help="The absolute path to the certificate file")
4786 certReplace.set_defaults(func=certificateReplace)
4787
Marri Devender Rao34646402019-07-01 05:46:03 -05004788 certDisplay = certMgmt_subproc.add_parser('display',
4789 help="Print the certificate")
4790 certDisplay.add_argument('type', choices=['server', 'client', 'authority'],
4791 help="certificate type to display")
4792 certDisplay.set_defaults(func=certificateDisplay)
4793
Marri Devender Raoa208ff82019-07-01 05:51:27 -05004794 certList = certMgmt_subproc.add_parser('list',
4795 help="Certificate list")
4796 certList.set_defaults(func=certificateList)
4797
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004798 certGenerateCSR = certMgmt_subproc.add_parser('generatecsr', help="Generate CSR")
4799 certGenerateCSR.add_argument('type', choices=['server', 'client', 'authority'],
4800 help="Generate CSR")
4801 certGenerateCSR.add_argument('city',
4802 help="The city or locality of the organization making the request")
4803 certGenerateCSR.add_argument('commonName',
4804 help="The fully qualified domain name of the component that is being secured.")
4805 certGenerateCSR.add_argument('country',
4806 help="The country of the organization making the request")
4807 certGenerateCSR.add_argument('organization',
4808 help="The name of the organization making the request.")
4809 certGenerateCSR.add_argument('organizationUnit',
4810 help="The name of the unit or division of the organization making the request.")
4811 certGenerateCSR.add_argument('state',
4812 help="The state, province, or region of the organization making the request.")
4813 certGenerateCSR.add_argument('keyPairAlgorithm', choices=['RSA', 'EC'],
4814 help="The type of key pair for use with signing algorithms.")
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004815 certGenerateCSR.add_argument('keyCurveId',
4816 help="The curve ID to be used with the key, if needed based on the value of the 'KeyPairAlgorithm' parameter.")
4817 certGenerateCSR.add_argument('contactPerson',
4818 help="The name of the user making the request")
4819 certGenerateCSR.add_argument('email',
4820 help="The email address of the contact within the organization")
4821 certGenerateCSR.add_argument('alternativeNames',
4822 help="Additional hostnames of the component that is being secured")
4823 certGenerateCSR.add_argument('givenname',
4824 help="The given name of the user making the request")
4825 certGenerateCSR.add_argument('surname',
4826 help="The surname of the user making the request")
4827 certGenerateCSR.add_argument('unstructuredname',
4828 help="he unstructured name of the subject")
4829 certGenerateCSR.add_argument('initials',
4830 help="The initials of the user making the request")
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004831 certGenerateCSR.set_defaults(func=certificateGenerateCSR)
4832
Matt Spinler7d426c22018-09-24 14:42:07 -05004833 # local users
4834 parser_users = subparsers.add_parser("local_users", help="Work with local users")
4835 parser_users.add_argument('local_users', choices=['disableall','enableall', 'queryenabled'], help="Disable, enable or query local user accounts")
4836 parser_users.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4837 parser_users.set_defaults(func=localUsers)
4838
Ratan Gupta9166cd22018-10-01 18:09:40 +05304839 #LDAP
4840 parser_ldap = subparsers.add_parser("ldap", help="LDAP controls")
4841 ldap_sub = parser_ldap.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
4842
4843 #configure and enable LDAP
4844 parser_ldap_config = ldap_sub.add_parser("enable", help="Configure and enables the LDAP")
4845 parser_ldap_config.add_argument("-a", "--uri", required=True, help="Set LDAP server URI")
4846 parser_ldap_config.add_argument("-B", "--bindDN", required=True, help="Set the bind DN of the LDAP server")
4847 parser_ldap_config.add_argument("-b", "--baseDN", required=True, help="Set the base DN of the LDAP server")
4848 parser_ldap_config.add_argument("-p", "--bindPassword", required=True, help="Set the bind password of the LDAP server")
4849 parser_ldap_config.add_argument("-S", "--scope", choices=['sub','one', 'base'],
4850 help='Specifies the search scope:subtree, one level or base object.')
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004851 parser_ldap_config.add_argument("-t", "--serverType", required=True, choices=['ActiveDirectory','OpenLDAP'],
Ratan Gupta9166cd22018-10-01 18:09:40 +05304852 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004853 parser_ldap_config.add_argument("-g","--groupAttrName", required=False, default='', help="Group Attribute Name")
4854 parser_ldap_config.add_argument("-u","--userAttrName", required=False, default='', help="User Attribute Name")
4855 parser_ldap_config.set_defaults(func=enableLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05304856
4857 # disable LDAP
4858 parser_disable_ldap = ldap_sub.add_parser("disable", help="disables the LDAP")
4859 parser_disable_ldap.set_defaults(func=disableLDAP)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004860 # view-config
4861 parser_ldap_config = \
4862 ldap_sub.add_parser("view-config", help="prints out a list of all \
4863 LDAPS's configured properties")
4864 parser_ldap_config.set_defaults(func=viewLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05304865
Ratan Guptafeee6372018-10-17 23:25:51 +05304866 #create group privilege mapping
4867 parser_ldap_mapper = ldap_sub.add_parser("privilege-mapper", help="LDAP group privilege controls")
4868 parser_ldap_mapper_sub = parser_ldap_mapper.add_subparsers(title='subcommands', description='valid subcommands',
4869 help="sub-command help", dest='command')
4870
4871 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 -05004872 parser_ldap_mapper_create.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4873 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304874 parser_ldap_mapper_create.add_argument("-g","--groupName",required=True,help="Group Name")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004875 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 +05304876 parser_ldap_mapper_create.set_defaults(func=createPrivilegeMapping)
4877
4878 #list group privilege mapping
4879 parser_ldap_mapper_list = parser_ldap_mapper_sub.add_parser("list",help="List privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004880 parser_ldap_mapper_list.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4881 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304882 parser_ldap_mapper_list.set_defaults(func=listPrivilegeMapping)
4883
4884 #delete group privilege mapping
4885 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("delete",help="Delete privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004886 parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4887 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304888 parser_ldap_mapper_delete.add_argument("-g","--groupName",required=True,help="Group Name")
4889 parser_ldap_mapper_delete.set_defaults(func=deletePrivilegeMapping)
4890
Sivas SRR78835272018-11-27 05:27:19 -06004891 #deleteAll group privilege mapping
4892 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("purge",help="Delete All privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004893 parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4894 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Sivas SRR78835272018-11-27 05:27:19 -06004895 parser_ldap_mapper_delete.set_defaults(func=deleteAllPrivilegeMapping)
4896
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004897 # set local user password
4898 parser_set_password = subparsers.add_parser("set_password",
4899 help="Set password of local user")
4900 parser_set_password.add_argument( "-p", "--password", required=True,
4901 help="Password of local user")
4902 parser_set_password.set_defaults(func=setPassword)
4903
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004904 # network
4905 parser_nw = subparsers.add_parser("network", help="network controls")
4906 nw_sub = parser_nw.add_subparsers(title='subcommands',
4907 description='valid subcommands',
4908 help="sub-command help",
4909 dest='command')
4910
4911 # enable DHCP
4912 parser_enable_dhcp = nw_sub.add_parser("enableDHCP",
4913 help="enables the DHCP on given "
4914 "Interface")
4915 parser_enable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004916 help="Name of the ethernet interface(it can"
4917 "be obtained by the "
4918 "command:network view-config)"
4919 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004920 parser_enable_dhcp.set_defaults(func=enableDHCP)
4921
4922 # disable DHCP
4923 parser_disable_dhcp = nw_sub.add_parser("disableDHCP",
4924 help="disables the DHCP on given "
4925 "Interface")
4926 parser_disable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004927 help="Name of the ethernet interface(it can"
4928 "be obtained by the "
4929 "command:network view-config)"
4930 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004931 parser_disable_dhcp.set_defaults(func=disableDHCP)
4932
4933 # get HostName
4934 parser_gethostname = nw_sub.add_parser("getHostName",
4935 help="prints out HostName")
4936 parser_gethostname.set_defaults(func=getHostname)
4937
4938 # set HostName
4939 parser_sethostname = nw_sub.add_parser("setHostName", help="sets HostName")
4940 parser_sethostname.add_argument("-H", "--HostName", required=True,
4941 help="A HostName for the BMC")
4942 parser_sethostname.set_defaults(func=setHostname)
4943
4944 # get domainname
4945 parser_getdomainname = nw_sub.add_parser("getDomainName",
4946 help="prints out DomainName of "
4947 "given Interface")
4948 parser_getdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004949 help="Name of the ethernet interface(it "
4950 "can be obtained by the "
4951 "command:network view-config)"
4952 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004953 parser_getdomainname.set_defaults(func=getDomainName)
4954
4955 # set domainname
4956 parser_setdomainname = nw_sub.add_parser("setDomainName",
4957 help="sets DomainName of given "
4958 "Interface")
4959 parser_setdomainname.add_argument("-D", "--DomainName", required=True,
4960 help="Ex: DomainName=Domain1,Domain2,...")
4961 parser_setdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004962 help="Name of the ethernet interface(it "
4963 "can be obtained by the "
4964 "command:network view-config)"
4965 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004966 parser_setdomainname.set_defaults(func=setDomainName)
4967
4968 # get MACAddress
4969 parser_getmacaddress = nw_sub.add_parser("getMACAddress",
4970 help="prints out MACAddress the "
4971 "given Interface")
4972 parser_getmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004973 help="Name of the ethernet interface(it "
4974 "can be obtained by the "
4975 "command:network view-config)"
4976 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004977 parser_getmacaddress.set_defaults(func=getMACAddress)
4978
4979 # set MACAddress
4980 parser_setmacaddress = nw_sub.add_parser("setMACAddress",
4981 help="sets MACAddress")
4982 parser_setmacaddress.add_argument("-MA", "--MACAddress", required=True,
4983 help="A MACAddress for the given "
4984 "Interface")
4985 parser_setmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004986 help="Name of the ethernet interface(it can"
4987 "be obtained by the "
4988 "command:network view-config)"
4989 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004990 parser_setmacaddress.set_defaults(func=setMACAddress)
4991
4992 # get DefaultGW
4993 parser_getdefaultgw = nw_sub.add_parser("getDefaultGW",
4994 help="prints out DefaultGateway "
4995 "the BMC")
4996 parser_getdefaultgw.set_defaults(func=getDefaultGateway)
4997
4998 # set DefaultGW
4999 parser_setdefaultgw = nw_sub.add_parser("setDefaultGW",
5000 help="sets DefaultGW")
5001 parser_setdefaultgw.add_argument("-GW", "--DefaultGW", required=True,
5002 help="A DefaultGateway for the BMC")
5003 parser_setdefaultgw.set_defaults(func=setDefaultGateway)
5004
5005 # view network Config
5006 parser_ldap_config = nw_sub.add_parser("view-config", help="prints out a "
5007 "list of all network's configured "
5008 "properties")
5009 parser_ldap_config.set_defaults(func=viewNWConfig)
5010
5011 # get DNS
5012 parser_getDNS = nw_sub.add_parser("getDNS",
5013 help="prints out DNS servers on the "
5014 "given interface")
5015 parser_getDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005016 help="Name of the ethernet interface(it can"
5017 "be obtained by the "
5018 "command:network view-config)"
5019 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005020 parser_getDNS.set_defaults(func=getDNS)
5021
5022 # set DNS
5023 parser_setDNS = nw_sub.add_parser("setDNS",
5024 help="sets DNS servers on the given "
5025 "interface")
5026 parser_setDNS.add_argument("-d", "--DNSServers", required=True,
5027 help="Ex: DNSSERVERS=DNS1,DNS2,...")
5028 parser_setDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005029 help="Name of the ethernet interface(it can"
5030 "be obtained by the "
5031 "command:network view-config)"
5032 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005033 parser_setDNS.set_defaults(func=setDNS)
5034
5035 # get NTP
5036 parser_getNTP = nw_sub.add_parser("getNTP",
5037 help="prints out NTP servers on the "
5038 "given interface")
5039 parser_getNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005040 help="Name of the ethernet interface(it can"
5041 "be obtained by the "
5042 "command:network view-config)"
5043 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005044 parser_getNTP.set_defaults(func=getNTP)
5045
5046 # set NTP
5047 parser_setNTP = nw_sub.add_parser("setNTP",
5048 help="sets NTP servers on the given "
5049 "interface")
5050 parser_setNTP.add_argument("-N", "--NTPServers", required=True,
5051 help="Ex: NTPSERVERS=NTP1,NTP2,...")
5052 parser_setNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005053 help="Name of the ethernet interface(it can"
5054 "be obtained by the "
5055 "command:network view-config)"
5056 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005057 parser_setNTP.set_defaults(func=setNTP)
5058
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005059 # configure IP
5060 parser_ip_config = nw_sub.add_parser("addIP", help="Sets IP address to"
5061 "given interface")
5062 parser_ip_config.add_argument("-a", "--address", required=True,
5063 help="IP address of given interface")
5064 parser_ip_config.add_argument("-gw", "--gateway", required=False, default='',
5065 help="The gateway for given interface")
5066 parser_ip_config.add_argument("-l", "--prefixLength", required=True,
5067 help="The prefixLength of IP address")
Sunitha Harish0baf6372019-07-31 03:59:03 -05005068 parser_ip_config.add_argument("-p", "--type", required=True,
5069 choices=['ipv4', 'ipv6'],
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005070 help="The protocol type of the given"
5071 "IP address")
5072 parser_ip_config.add_argument("-I", "--Interface", required=True,
5073 help="Name of the ethernet interface(it can"
5074 "be obtained by the "
5075 "command:network view-config)"
5076 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5077 parser_ip_config.set_defaults(func=addIP)
5078
5079 # getIP
5080 parser_getIP = nw_sub.add_parser("getIP", help="prints out IP address"
5081 "of given interface")
5082 parser_getIP.add_argument("-I", "--Interface", required=True,
5083 help="Name of the ethernet interface(it can"
5084 "be obtained by the command:network view-config)"
5085 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5086 parser_getIP.set_defaults(func=getIP)
5087
5088 # rmIP
5089 parser_rmIP = nw_sub.add_parser("rmIP", help="deletes IP address"
5090 "of given interface")
5091 parser_rmIP.add_argument("-a", "--address", required=True,
5092 help="IP address to remove form given Interface")
5093 parser_rmIP.add_argument("-I", "--Interface", required=True,
5094 help="Name of the ethernet interface(it can"
5095 "be obtained by the command:network view-config)"
5096 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5097 parser_rmIP.set_defaults(func=deleteIP)
5098
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06005099 # add VLAN
5100 parser_create_vlan = nw_sub.add_parser("addVLAN", help="enables VLAN "
5101 "on given interface with given "
5102 "VLAN Identifier")
5103 parser_create_vlan.add_argument("-I", "--Interface", required=True,
5104 choices=['eth0', 'eth1'],
5105 help="Name of the ethernet interface")
5106 parser_create_vlan.add_argument("-n", "--Identifier", required=True,
5107 help="VLAN Identifier")
5108 parser_create_vlan.set_defaults(func=addVLAN)
5109
5110 # delete VLAN
5111 parser_delete_vlan = nw_sub.add_parser("deleteVLAN", help="disables VLAN "
5112 "on given interface with given "
5113 "VLAN Identifier")
5114 parser_delete_vlan.add_argument("-I", "--Interface", required=True,
5115 help="Name of the ethernet interface(it can"
5116 "be obtained by the "
5117 "command:network view-config)"
5118 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5119 parser_delete_vlan.set_defaults(func=deleteVLAN)
5120
5121 # viewDHCPConfig
5122 parser_viewDHCPConfig = nw_sub.add_parser("viewDHCPConfig",
5123 help="Shows DHCP configured "
5124 "Properties")
5125 parser_viewDHCPConfig.set_defaults(func=viewDHCPConfig)
5126
5127 # configureDHCP
5128 parser_configDHCP = nw_sub.add_parser("configureDHCP",
5129 help="Configures/updates DHCP "
5130 "Properties")
5131 parser_configDHCP.add_argument("-d", "--DNSEnabled", type=str2bool,
5132 required=True, help="Sets DNSEnabled property")
5133 parser_configDHCP.add_argument("-n", "--HostNameEnabled", type=str2bool,
5134 required=True,
5135 help="Sets HostNameEnabled property")
5136 parser_configDHCP.add_argument("-t", "--NTPEnabled", type=str2bool,
5137 required=True,
5138 help="Sets NTPEnabled property")
5139 parser_configDHCP.add_argument("-s", "--SendHostNameEnabled", type=str2bool,
5140 required=True,
5141 help="Sets SendHostNameEnabled property")
5142 parser_configDHCP.set_defaults(func=configureDHCP)
5143
5144 # network factory reset
5145 parser_nw_reset = nw_sub.add_parser("nwReset",
5146 help="Resets networks setting to "
5147 "factory defaults. "
5148 "note:Reset settings will be applied "
5149 "after BMC reboot")
5150 parser_nw_reset.set_defaults(func=nwReset)
5151
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005152 return parser
5153
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005154def main(argv=None):
Justin Thalere412dc22018-01-12 16:28:24 -06005155 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005156 main function for running the command line utility as a sub application
5157 """
5158 global toolVersion
Joy Onyerikwu182c3a32019-10-15 08:33:59 -05005159 toolVersion = "1.18"
Sunitha Harishc99faba2019-07-19 06:55:22 -05005160 global isRedfishSupport
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05005161
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005162 parser = createCommandParser()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005163 args = parser.parse_args(argv)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005164
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005165 totTimeStart = int(round(time.time()*1000))
5166
5167 if(sys.version_info < (3,0)):
5168 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
5169 if sys.version_info >= (3,0):
5170 requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Justin Thalere412dc22018-01-12 16:28:24 -06005171 if (args.version):
Justin Thaler22b1bb52018-03-15 13:31:32 -05005172 print("Version: "+ toolVersion)
Justin Thalere412dc22018-01-12 16:28:24 -06005173 sys.exit(0)
5174 if (hasattr(args, 'fileloc') and args.fileloc is not None and 'print' in args.command):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005175 mysess = None
Justin Thalere412dc22018-01-12 16:28:24 -06005176 print(selPrint('N/A', args, mysess))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005177 else:
Justin Thalere412dc22018-01-12 16:28:24 -06005178 if(hasattr(args, 'host') and hasattr(args,'user')):
5179 if (args.askpw):
5180 pw = getpass.getpass()
5181 elif(args.PW is not None):
5182 pw = args.PW
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05005183 elif(args.PWenvvar):
5184 pw = os.environ['OPENBMCTOOL_PASSWORD']
Justin Thalere412dc22018-01-12 16:28:24 -06005185 else:
5186 print("You must specify a password")
5187 sys.exit()
5188 logintimeStart = int(round(time.time()*1000))
Joy Onyerikwu182c3a32019-10-15 08:33:59 -05005189 mysess = login(args.host, args.user, pw, args.json,
5190 args.command == 'set_password')
Sunitha Harish336cda22019-07-23 02:02:52 -05005191 if(mysess == None):
5192 print("Login Failed!")
5193 sys.exit()
Justin Thalera9415b42018-05-25 19:40:13 -05005194 if(sys.version_info < (3,0)):
5195 if isinstance(mysess, basestring):
5196 print(mysess)
5197 sys.exit(1)
5198 elif sys.version_info >= (3,0):
5199 if isinstance(mysess, str):
5200 print(mysess)
5201 sys.exit(1)
Justin Thalere412dc22018-01-12 16:28:24 -06005202 logintimeStop = int(round(time.time()*1000))
Sunitha Harishc99faba2019-07-19 06:55:22 -05005203 isRedfishSupport = redfishSupportPresent(args.host,mysess)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005204 commandTimeStart = int(round(time.time()*1000))
Justin Thalere412dc22018-01-12 16:28:24 -06005205 output = args.func(args.host, args, mysess)
5206 commandTimeStop = int(round(time.time()*1000))
Justin Thaler761484a2019-03-26 19:20:23 -05005207 if isinstance(output, dict):
5208 print(json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
5209 else:
5210 print(output)
Justin Thalere412dc22018-01-12 16:28:24 -06005211 if (mysess is not None):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005212 logout(args.host, args.user, pw, mysess, args.json)
5213 if(args.procTime):
Justin Thalere412dc22018-01-12 16:28:24 -06005214 print("Total time: " + str(int(round(time.time()*1000))- totTimeStart))
5215 print("loginTime: " + str(logintimeStop - logintimeStart))
5216 print("command Time: " + str(commandTimeStop - commandTimeStart))
5217 else:
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05005218 print("usage:\n"
5219 " OPENBMCTOOL_PASSWORD=secret # if using -E\n"
5220 " openbmctool.py [-h] -H HOST -U USER {-A | -P PW | -E} [-j]\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06005221 "\t[-t POLICYTABLELOC] [-V]\n" +
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05005222 "\t{fru,sensors,sel,chassis,collect_service_data, \
5223 health_check,dump,bmc,mc,gardclear,firmware,logging}\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06005224 "\t...\n" +
5225 "openbmctool.py: error: the following arguments are required: -H/--host, -U/--user")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005226 sys.exit()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005227
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005228if __name__ == '__main__':
Justin Thalere412dc22018-01-12 16:28:24 -06005229 """
5230 main function when called from the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005231
5232 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005233 import sys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005234
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005235 isTTY = sys.stdout.isatty()
5236 assert sys.version_info >= (2,7)
5237 main()