blob: 4786f818878b4fc3040bc72265e492ebcf54e7a9 [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 Thalerb4256672020-04-07 19:38:26 -050039import traceback
Justin Thalerf9aee3e2017-12-05 12:11:09 -060040
Ravi Tejad8be0b42020-03-18 14:31:46 -050041
42MAX_NBD_PACKET_SIZE = 131088
Matt Spinler220c3c42019-01-04 15:09:29 -060043jsonHeader = {'Content-Type' : 'application/json'}
44xAuthHeader = {}
Justin Thaler27197622019-01-23 14:42:11 -060045baseTimeout = 60
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -050046serverTypeMap = {
47 'ActiveDirectory' : 'active_directory',
48 'OpenLDAP' : 'openldap'
49 }
Matt Spinler220c3c42019-01-04 15:09:29 -060050
Ravi Tejad8be0b42020-03-18 14:31:46 -050051class NBDPipe:
52
53 def openHTTPSocket(self,args):
54
55 try:
56 _create_unverified_https_context = ssl._create_unverified_context
57 except AttributeError:
58 # Legacy Python that doesn't verify HTTPS certificates by default
59 pass
60 else:
61 # Handle target environment that doesn't support HTTPS verification
62 ssl._create_default_https_context = _create_unverified_https_context
63
64
65 token = gettoken(args)
66 self.conn = http.client.HTTPSConnection(args.host,port=443)
67 URI = "/redfish/v1/Systems/system/LogServices/SystemDump/Entries/"+str(args.dumpNum)+"/Actions/Oem/OpenBmc/LogEntry.DownloadLog"
68 self.conn.request("POST",URI, headers={"X-Auth-Token":token})
69
70 def openTCPSocket(self):
71 # Create a TCP/IP socket
72 self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
73 # Connect the socket to the port where the server is listening
74 server_address = ('localhost', 1043)
75 self.tcp.connect(server_address)
76
77 def waitformessage(self):
78 inputs = [self.conn.sock,self.tcp]
79 outputs = []
80 message_queues = {}
81 while True:
82 readable, writable, exceptional = select.select(
83 inputs, outputs, inputs)
84
85 for s in readable:
86 if s is self.conn.sock:
87
88 data = self.conn.sock.recv(MAX_NBD_PACKET_SIZE)
89 print("<<HTTP")
Ravi Tejad8be0b42020-03-18 14:31:46 -050090 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")
Ravi Tejad8be0b42020-03-18 14:31:46 -0500100 if data:
101 self.conn.sock.send(data)
102 else:
103 print("NBD server closed the connection")
104 self.conn.sock.close()
105 self.tcp.close()
106 sys.exit(1)
107 for s in exceptional:
108 inputs.remove(s)
109 print("Exceptional closing the socket")
110 s.close()
111
112def getsize(host,args,session):
113 url = "https://"+host+"/redfish/v1/Systems/system/LogServices/SystemDump/Entries/"+str(args.dumpNum)
Ravi Tejad8be0b42020-03-18 14:31:46 -0500114 try:
115 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
116 if resp.status_code==200:
117 size = resp.json()["Oem"]["OpenBmc"]['SizeInB']
Ravi Tejad8be0b42020-03-18 14:31:46 -0500118 return size
119 else:
120 return "Failed get Size"
121 except(requests.exceptions.Timeout):
122 return connectionErrHandler(args.json, "Timeout", None)
123
124 except(requests.exceptions.ConnectionError) as err:
125 return connectionErrHandler(args.json, "ConnectionError", err)
126
127def gettoken(args):
128 mysess = requests.session()
129 resp = mysess.post('https://'+args.host+'/login', headers=jsonHeader,json={"data":[args.user,args.PW]},verify=False)
130 if resp.status_code == 200:
131 cookie = resp.headers['Set-Cookie']
132 match = re.search('SESSION=(\w+);', cookie)
133 return match.group(1)
134
135
136
137def get_pid(name):
138 try:
139 pid = map(int, check_output(["pidof", "-s",name]))
140 except Exception:
141 pid = 0
142
143 return pid
144
145def findThisProcess( process_name ):
146 ps = subprocess.Popen("ps -eaf | grep "+process_name, shell=True, stdout=subprocess.PIPE)
147 output = ps.stdout.read()
148 ps.stdout.close()
149 ps.wait()
150 pid = get_pid(process_name)
Ravi Tejad8be0b42020-03-18 14:31:46 -0500151 return output
152
153def isThisProcessRunning( process_name ):
154 pid = get_pid(process_name)
155 if (pid == 0 ):
156 return False
157 else:
158 return True
159
160def NBDSetup(host,args,session):
161 user=os.getenv("SUDO_USER")
162 if user is None:
163 path = os.getcwd()
164 nbdServerPath = path + "/nbd-server"
Ravi Tejad8be0b42020-03-18 14:31:46 -0500165 if not os.path.exists(nbdServerPath):
166 print("Error: this program did not run as sudo!\nplease copy nbd-server to current directory and run script again")
167 exit()
168
169 if isThisProcessRunning('nbd-server') == True:
170 print("nbd-server already Running! killing the nbd-server")
171 os.system('killall nbd-server')
172
173 if (args.dumpSaveLoc is not None):
174 if(os.path.exists(args.dumpSaveLoc)):
175 print("Error: File already exists.")
176 exit()
177
178 fp= open(args.dumpSaveLoc,"w")
179 sizeInBytes = getsize(host,args,session)
180 #Round off size to mutiples of 1024
181 size = int(sizeInBytes)
Ravi Tejad8be0b42020-03-18 14:31:46 -0500182 mod = size % 1024
183 if mod :
184 roundoff = 1024 - mod
185 size = size + roundoff
186
187 cmd = 'chmod 777 ' + args.dumpSaveLoc
188 os.system(cmd)
189
190 #Run truncate to create file with given size
191 cmd = 'truncate -s ' + str(size) + ' '+ args.dumpSaveLoc
192 os.system(cmd)
193
194 if user is None:
195 cmd = './nbd-server 1043 '+ args.dumpSaveLoc
196 else:
197 cmd = 'nbd-server 1043 '+ args.dumpSaveLoc
198 os.system(cmd)
199
200
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600201def hilight(textToColor, color, bold):
Justin Thalere412dc22018-01-12 16:28:24 -0600202 """
203 Used to add highlights to various text for displaying in a terminal
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600204
Justin Thalere412dc22018-01-12 16:28:24 -0600205 @param textToColor: string, the text to be colored
206 @param color: string, used to color the text red or green
207 @param bold: boolean, used to bold the textToColor
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600208 @return: Buffered reader containing the modified string.
209 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600210 if(sys.platform.__contains__("win")):
211 if(color == "red"):
212 os.system('color 04')
213 elif(color == "green"):
214 os.system('color 02')
215 else:
216 os.system('color') #reset to default
217 return textToColor
218 else:
219 attr = []
220 if(color == "red"):
221 attr.append('31')
222 elif(color == "green"):
223 attr.append('32')
224 else:
225 attr.append('0')
226 if bold:
227 attr.append('1')
228 else:
229 attr.append('0')
230 return '\x1b[%sm%s\x1b[0m' % (';'.join(attr),textToColor)
231
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600232def connectionErrHandler(jsonFormat, errorStr, err):
Justin Thalere412dc22018-01-12 16:28:24 -0600233 """
234 Error handler various connection errors to bmcs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600235
236 @param jsonFormat: boolean, used to output in json format with an error code.
Justin Thalere412dc22018-01-12 16:28:24 -0600237 @param errorStr: string, used to color the text red or green
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600238 @param err: string, the text from the exception
239 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600240 if errorStr == "Timeout":
241 if not jsonFormat:
242 return("FQPSPIN0000M: Connection timed out. Ensure you have network connectivity to the bmc")
243 else:
Justin Thaler115bca72018-05-25 19:29:08 -0500244 conerror = {}
245 conerror['CommonEventID'] = 'FQPSPIN0000M'
246 conerror['sensor']="N/A"
247 conerror['state']="N/A"
248 conerror['additionalDetails'] = "N/A"
249 conerror['Message']="Connection timed out. Ensure you have network connectivity to the BMC"
250 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."
251 conerror['Serviceable']="Yes"
252 conerror['CallHomeCandidate']= "No"
253 conerror['Severity'] = "Critical"
254 conerror['EventType'] = "Communication Failure/Timeout"
255 conerror['VMMigrationFlag'] = "Yes"
256 conerror["AffectedSubsystem"] = "Interconnect (Networking)"
257 conerror["timestamp"] = str(int(time.time()))
258 conerror["UserAction"] = "Verify network connectivity between the two systems and the bmc is functional."
259 eventdict = {}
260 eventdict['event0'] = conerror
261 eventdict['numAlerts'] = '1'
Justin Thaler115bca72018-05-25 19:29:08 -0500262 errorMessageStr = errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600263 return(errorMessageStr)
264 elif errorStr == "ConnectionError":
265 if not jsonFormat:
266 return("FQPSPIN0001M: " + str(err))
267 else:
Justin Thaler115bca72018-05-25 19:29:08 -0500268 conerror = {}
269 conerror['CommonEventID'] = 'FQPSPIN0001M'
270 conerror['sensor']="N/A"
271 conerror['state']="N/A"
272 conerror['additionalDetails'] = str(err)
273 conerror['Message']="Connection Error. View additional details for more information"
274 conerror['LengthyDescription'] = "A connection error to the specified BMC occurred and additional details are provided. Review these details to resolve the issue."
275 conerror['Serviceable']="Yes"
276 conerror['CallHomeCandidate']= "No"
277 conerror['Severity'] = "Critical"
278 conerror['EventType'] = "Communication Failure/Timeout"
279 conerror['VMMigrationFlag'] = "Yes"
280 conerror["AffectedSubsystem"] = "Interconnect (Networking)"
281 conerror["timestamp"] = str(int(time.time()))
282 conerror["UserAction"] = "Correct the issue highlighted in additional details and try again"
283 eventdict = {}
284 eventdict['event0'] = conerror
285 eventdict['numAlerts'] = '1'
Justin Thaler115bca72018-05-25 19:29:08 -0500286 errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600287 return(errorMessageStr)
Justin Thaler115bca72018-05-25 19:29:08 -0500288
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600289 else:
290 return("Unknown Error: "+ str(err))
291
Justin Thalere412dc22018-01-12 16:28:24 -0600292
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600293def setColWidth(keylist, numCols, dictForOutput, colNames):
Justin Thalere412dc22018-01-12 16:28:24 -0600294 """
295 Sets the output width of the columns to display
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600296
297 @param keylist: list, list of strings representing the keys for the dictForOutput
Justin Thalere412dc22018-01-12 16:28:24 -0600298 @param numcols: the total number of columns in the final output
299 @param dictForOutput: dictionary, contains the information to print to the screen
300 @param colNames: list, The strings to use for the column headings, in order of the keylist
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600301 @return: A list of the column widths for each respective column.
Justin Thalere412dc22018-01-12 16:28:24 -0600302 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600303 colWidths = []
304 for x in range(0, numCols):
305 colWidths.append(0)
306 for key in dictForOutput:
307 for x in range(0, numCols):
308 colWidths[x] = max(colWidths[x], len(str(dictForOutput[key][keylist[x]])))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600309
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600310 for x in range(0, numCols):
311 colWidths[x] = max(colWidths[x], len(colNames[x])) +2
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600312
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600313 return colWidths
314
315def loadPolicyTable(pathToPolicyTable):
Justin Thalere412dc22018-01-12 16:28:24 -0600316 """
317 loads a json based policy table into a dictionary
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600318
Justin Thalere412dc22018-01-12 16:28:24 -0600319 @param value: boolean, the value to convert
320 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600321 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600322 policyTable = {}
323 if(os.path.exists(pathToPolicyTable)):
324 with open(pathToPolicyTable, 'r') as stream:
325 try:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600326 contents =json.load(stream)
327 policyTable = contents['events']
Justin Thalere412dc22018-01-12 16:28:24 -0600328 except Exception as err:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600329 print(err)
330 return policyTable
331
Justin Thalere412dc22018-01-12 16:28:24 -0600332
333def boolToString(value):
334 """
335 converts a boolean value to a human readable string value
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600336
Justin Thalere412dc22018-01-12 16:28:24 -0600337 @param value: boolean, the value to convert
338 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600339 """
Justin Thalere412dc22018-01-12 16:28:24 -0600340 if(value):
341 return "Yes"
342 else:
343 return "No"
344
Justin Thalera6b5df72018-07-16 11:10:07 -0500345def stringToInt(text):
346 """
347 returns an integer if the string can be converted, otherwise returns the string
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600348
Justin Thalera6b5df72018-07-16 11:10:07 -0500349 @param text: the string to try to convert to an integer
350 """
351 if text.isdigit():
352 return int(text)
353 else:
354 return text
Justin Thalere412dc22018-01-12 16:28:24 -0600355
Justin Thalera6b5df72018-07-16 11:10:07 -0500356def naturalSort(text):
357 """
358 provides a way to naturally sort a list
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600359
Justin Thalera6b5df72018-07-16 11:10:07 -0500360 @param text: the key to convert for sorting
361 @return list containing the broken up string parts by integers and strings
362 """
363 stringPartList = []
364 for c in re.split('(\d+)', text):
365 stringPartList.append(stringToInt(c))
366 return stringPartList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600367
Justin Thalere412dc22018-01-12 16:28:24 -0600368def tableDisplay(keylist, colNames, output):
369 """
370 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600371
Justin Thalere412dc22018-01-12 16:28:24 -0600372 @param keylist: list, keys for the output dictionary, ordered by colNames
373 @param colNames: Names for the Table of the columns
374 @param output: The dictionary of data to display
375 @return: Session object
376 """
377 colWidth = setColWidth(keylist, len(colNames), output, colNames)
378 row = ""
379 outputText = ""
380 for i in range(len(colNames)):
381 if (i != 0): row = row + "| "
382 row = row + colNames[i].ljust(colWidth[i])
383 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600384
Justin Thalera6b5df72018-07-16 11:10:07 -0500385 output_keys = list(output.keys())
386 output_keys.sort(key=naturalSort)
387 for key in output_keys:
Justin Thalere412dc22018-01-12 16:28:24 -0600388 row = ""
Justin Thaler8fe0c732018-07-24 14:32:35 -0500389 for i in range(len(keylist)):
Justin Thalere412dc22018-01-12 16:28:24 -0600390 if (i != 0): row = row + "| "
391 row = row + output[key][keylist[i]].ljust(colWidth[i])
392 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600393
Justin Thalere412dc22018-01-12 16:28:24 -0600394 return outputText
395
Justin Thaler22b1bb52018-03-15 13:31:32 -0500396def checkFWactivation(host, args, session):
397 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600398 Checks the software inventory for an image that is being activated.
399
Justin Thaler22b1bb52018-03-15 13:31:32 -0500400 @return: True if an image is being activated, false is no activations are happening
401 """
402 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thaler22b1bb52018-03-15 13:31:32 -0500403 try:
Justin Thaler27197622019-01-23 14:42:11 -0600404 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -0500405 except(requests.exceptions.Timeout):
406 print(connectionErrHandler(args.json, "Timeout", None))
407 return(True)
408 except(requests.exceptions.ConnectionError) as err:
409 print( connectionErrHandler(args.json, "ConnectionError", err))
410 return True
Justin Thaler3a5771b2019-01-23 14:31:52 -0600411 fwInfo = resp.json()['data']
Justin Thaler22b1bb52018-03-15 13:31:32 -0500412 for key in fwInfo:
413 if 'Activation' in fwInfo[key]:
414 if 'Activating' in fwInfo[key]['Activation'] or 'Activating' in fwInfo[key]['RequestedActivation']:
415 return True
416 return False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600417
Joy Onyerikwu182c3a32019-10-15 08:33:59 -0500418def login(host, username, pw,jsonFormat, allowExpiredPassword):
Justin Thalere412dc22018-01-12 16:28:24 -0600419 """
420 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600421
Justin Thalere412dc22018-01-12 16:28:24 -0600422 @param host: string, the hostname or IP address of the bmc to log into
423 @param username: The user name for the bmc to log into
424 @param pw: The password for the BMC to log into
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600425 @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 -0500426 @param allowExpiredPassword: true, if the requested operation should
427 be allowed when the password is expired
Justin Thalere412dc22018-01-12 16:28:24 -0600428 @return: Session object
429 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600430 if(jsonFormat==False):
431 print("Attempting login...")
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600432 mysess = requests.session()
433 try:
Justin Thaler27197622019-01-23 14:42:11 -0600434 r = mysess.post('https://'+host+'/login', headers=jsonHeader, json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
Sunitha Harish336cda22019-07-23 02:02:52 -0500435 if r.status_code == 200:
436 cookie = r.headers['Set-Cookie']
437 match = re.search('SESSION=(\w+);', cookie)
438 if match:
439 xAuthHeader['X-Auth-Token'] = match.group(1)
440 jsonHeader.update(xAuthHeader)
441 loginMessage = json.loads(r.text)
442 if (loginMessage['status'] != "ok"):
443 print(loginMessage["data"]["description"].encode('utf-8'))
444 sys.exit(1)
Joy Onyerikwu182c3a32019-10-15 08:33:59 -0500445 if (('extendedMessage' in r.json()) and
446 ('The password for this account must be changed' in r.json()['extendedMessage'])):
447 if not allowExpiredPassword:
448 print("The password for this system has expired and must be changed"+
449 "\nsee openbmctool.py set_password --help")
450 logout(host, username, pw, mysess, jsonFormat)
451 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600452# if(sys.version_info < (3,0)):
453# urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
454# if sys.version_info >= (3,0):
455# requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Sunitha Harish336cda22019-07-23 02:02:52 -0500456 return mysess
457 else:
458 return None
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600459 except(requests.exceptions.Timeout):
Justin Thaler115bca72018-05-25 19:29:08 -0500460 return (connectionErrHandler(jsonFormat, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600461 except(requests.exceptions.ConnectionError) as err:
Justin Thaler115bca72018-05-25 19:29:08 -0500462 return (connectionErrHandler(jsonFormat, "ConnectionError", err))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600463
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600464
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600465def logout(host, username, pw, session, jsonFormat):
Justin Thalere412dc22018-01-12 16:28:24 -0600466 """
467 Logs out of the bmc and terminates the session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600468
Justin Thalere412dc22018-01-12 16:28:24 -0600469 @param host: string, the hostname or IP address of the bmc to log out of
470 @param username: The user name for the bmc to log out of
471 @param pw: The password for the BMC to log out of
472 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600473 @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true.
474 """
Justin Thalere412dc22018-01-12 16:28:24 -0600475 try:
Justin Thaler27197622019-01-23 14:42:11 -0600476 r = session.post('https://'+host+'/logout', headers=jsonHeader,json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600477 except(requests.exceptions.Timeout):
478 print(connectionErrHandler(jsonFormat, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600479
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600480 if(jsonFormat==False):
Matt Spinlereae05b02019-01-24 12:59:34 -0600481 if r.status_code == 200:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600482 print('User ' +username + ' has been logged out')
483
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600484
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600485def fru(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600486 """
487 prints out the system inventory. deprecated see fruPrint and fruList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600488
Justin Thalere412dc22018-01-12 16:28:24 -0600489 @param host: string, the hostname or IP address of the bmc
490 @param args: contains additional arguments used by the fru sub command
491 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600492 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
493 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600494 #url="https://"+host+"/org/openbmc/inventory/system/chassis/enumerate"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600495
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600496 #print(url)
497 #res = session.get(url, headers=httpHeader, verify=False)
498 #print(res.text)
499 #sample = res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600500
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600501 #inv_list = json.loads(sample)["data"]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600502
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600503 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600504 try:
Justin Thaler27197622019-01-23 14:42:11 -0600505 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600506 except(requests.exceptions.Timeout):
507 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600508
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600509 sample = res.text
510# inv_list.update(json.loads(sample)["data"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600511#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600512# #determine column width's
513# colNames = ["FRU Name", "FRU Type", "Has Fault", "Is FRU", "Present", "Version"]
514# colWidths = setColWidth(["FRU Name", "fru_type", "fault", "is_fru", "present", "version"], 6, inv_list, colNames)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600515#
516# 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 -0600517# "Present".ljust(colWidths[4]) + "Version".ljust(colWidths[5]))
518# format the output
519# for key in sorted(inv_list.keys()):
520# keyParts = key.split("/")
521# isFRU = "True" if (inv_list[key]["is_fru"]==1) else "False"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600522#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600523# fruEntry = (keyParts[len(keyParts) - 1].ljust(colWidths[0]) + inv_list[key]["fru_type"].ljust(colWidths[1])+
524# inv_list[key]["fault"].ljust(colWidths[2])+isFRU.ljust(colWidths[3])+
525# inv_list[key]["present"].ljust(colWidths[4])+ inv_list[key]["version"].ljust(colWidths[5]))
526# if(isTTY):
527# if(inv_list[key]["is_fru"] == 1):
528# color = "green"
529# bold = True
530# else:
531# color='black'
532# bold = False
533# fruEntry = hilight(fruEntry, color, bold)
534# print (fruEntry)
535 return sample
Justin Thalere412dc22018-01-12 16:28:24 -0600536
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600537def fruPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600538 """
539 prints out all inventory
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600540
Justin Thalere412dc22018-01-12 16:28:24 -0600541 @param host: string, the hostname or IP address of the bmc
542 @param args: contains additional arguments used by the fru sub command
543 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600544 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
545 @return returns the total fru list.
546 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600547 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600548 try:
Justin Thaler27197622019-01-23 14:42:11 -0600549 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600550 except(requests.exceptions.Timeout):
551 return(connectionErrHandler(args.json, "Timeout", None))
552
Justin Thaler3a5771b2019-01-23 14:31:52 -0600553 frulist={}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600554# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600555 if res.status_code==200:
556 frulist['Hardware'] = res.json()['data']
557 else:
558 if not args.json:
559 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
560 else:
561 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600562 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600563 try:
Justin Thaler27197622019-01-23 14:42:11 -0600564 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600565 except(requests.exceptions.Timeout):
566 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600567# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600568 if res.status_code==200:
569 frulist['Software'] = res.json()['data']
570 else:
571 if not args.json():
572 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
573 else:
574 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600575 return frulist
576
Justin Thalere412dc22018-01-12 16:28:24 -0600577
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600578def fruList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600579 """
580 prints out all inventory or only a specific specified item
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600581
Justin Thalere412dc22018-01-12 16:28:24 -0600582 @param host: string, the hostname or IP address of the bmc
583 @param args: contains additional arguments used by the fru sub command
584 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600585 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
586 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600587 if(args.items==True):
588 return fruPrint(host, args, session)
589 else:
Justin Thalere412dc22018-01-12 16:28:24 -0600590 return fruPrint(host, args, session)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600591
592
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600593
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600594def fruStatus(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600595 """
596 prints out the status of all FRUs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600597
Justin Thalere412dc22018-01-12 16:28:24 -0600598 @param host: string, the hostname or IP address of the bmc
599 @param args: contains additional arguments used by the fru sub command
600 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600601 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
602 """
Justin Thalere412dc22018-01-12 16:28:24 -0600603 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600604 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600605 res = session.get(url, headers=jsonHeader, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -0600606 except(requests.exceptions.Timeout):
607 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600608# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600609 frulist = res.json()['data']
Justin Thalere412dc22018-01-12 16:28:24 -0600610 frus = {}
611 for key in frulist:
612 component = frulist[key]
613 isFru = False
614 present = False
615 func = False
616 hasSels = False
617 keyPieces = key.split('/')
618 fruName = keyPieces[-1]
619 if 'core' in fruName: #associate cores to cpus
620 fruName = keyPieces[-2] + '-' + keyPieces[-1]
621 if 'Functional' in component:
622 if('Present' in component):
Justin Thalere412dc22018-01-12 16:28:24 -0600623 if 'FieldReplaceable' in component:
624 if component['FieldReplaceable'] == 1:
625 isFru = True
626 if "fan" in fruName:
627 isFru = True;
628 if component['Present'] == 1:
629 present = True
630 if component['Functional'] == 1:
631 func = True
632 if ((key + "/fault") in frulist):
633 hasSels = True;
634 if args.verbose:
635 if hasSels:
636 loglist = []
637 faults = frulist[key+"/fault"]['endpoints']
638 for item in faults:
639 loglist.append(item.split('/')[-1])
640 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
641 else:
642 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
643 else:
644 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
Justin Thalerfb9c81c2018-07-16 11:14:37 -0500645 elif "power_supply" in fruName or "powersupply" in fruName:
Justin Thalere412dc22018-01-12 16:28:24 -0600646 if component['Present'] ==1:
647 present = True
648 isFru = True
649 if ((key + "/fault") in frulist):
650 hasSels = True;
651 if args.verbose:
652 if hasSels:
653 loglist = []
654 faults = frulist[key+"/fault"]['endpoints']
Obihörnchenff8035f2018-12-05 21:07:37 +0100655 for item in faults:
656 loglist.append(item.split('/')[-1])
Justin Thalere412dc22018-01-12 16:28:24 -0600657 frus[fruName] = {"compName": fruName, "Functional": "No", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
658 else:
659 frus[fruName] = {"compName": fruName, "Functional": "Yes", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
660 else:
661 frus[fruName] = {"compName": fruName, "Functional": boolToString(not hasSels), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
662 if not args.json:
663 if not args.verbose:
664 colNames = ["Component", "Is a FRU", "Present", "Functional", "Has Logs"]
665 keylist = ["compName", "IsFru", "Present", "Functional", "hasSEL"]
666 else:
667 colNames = ["Component", "Is a FRU", "Present", "Functional", "Assoc. Log Number(s)"]
668 keylist = ["compName", "IsFru", "Present", "Functional", "selList"]
669 return tableDisplay(keylist, colNames, frus)
670 else:
671 return str(json.dumps(frus, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600672
Justin Thalere412dc22018-01-12 16:28:24 -0600673def sensor(host, args, session):
674 """
675 prints out all sensors
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600676
Justin Thalere412dc22018-01-12 16:28:24 -0600677 @param host: string, the hostname or IP address of the bmc
678 @param args: contains additional arguments used by the sensor sub command
679 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600680 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
681 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600682 url="https://"+host+"/xyz/openbmc_project/sensors/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600683 try:
Justin Thaler27197622019-01-23 14:42:11 -0600684 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600685 except(requests.exceptions.Timeout):
686 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600687
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600688 #Get OCC status
689 url="https://"+host+"/org/open_power/control/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600690 try:
Justin Thaler27197622019-01-23 14:42:11 -0600691 occres = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600692 except(requests.exceptions.Timeout):
693 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600694 if not args.json:
695 colNames = ['sensor', 'type', 'units', 'value', 'target']
Justin Thaler3a5771b2019-01-23 14:31:52 -0600696 sensors = res.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600697 output = {}
698 for key in sensors:
699 senDict = {}
700 keyparts = key.split("/")
Matt Spinler596ef742019-09-20 08:54:36 -0500701
702 # Associations like the following also show up here:
703 # /xyz/openbmc_project/sensors/<type>/<name>/<assoc-name>
704 # Skip them.
705 # Note: keyparts[0] = '' which is why there are 7 segments.
706 if len(keyparts) > 6:
707 continue
708
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600709 senDict['sensorName'] = keyparts[-1]
710 senDict['type'] = keyparts[-2]
Justin Thalere412dc22018-01-12 16:28:24 -0600711 try:
712 senDict['units'] = sensors[key]['Unit'].split('.')[-1]
713 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500714 senDict['units'] = "N/A"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600715 if('Scale' in sensors[key]):
716 scale = 10 ** sensors[key]['Scale']
717 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600718 scale = 1
Justin Thaler22b1bb52018-03-15 13:31:32 -0500719 try:
720 senDict['value'] = str(sensors[key]['Value'] * scale)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600721 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500722 if 'value' in sensors[key]:
723 senDict['value'] = sensors[key]['value']
724 else:
725 senDict['value'] = "N/A"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600726 if 'Target' in sensors[key]:
727 senDict['target'] = str(sensors[key]['Target'])
728 else:
729 senDict['target'] = 'N/A'
730 output[senDict['sensorName']] = senDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600731
Justin Thaler3a5771b2019-01-23 14:31:52 -0600732 occstatus = occres.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600733 if '/org/open_power/control/occ0' in occstatus:
734 occ0 = occstatus["/org/open_power/control/occ0"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600735 if occ0 == 1:
736 occ0 = 'Active'
737 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600738 occ0 = 'Inactive'
739 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
740 occ1 = occstatus["/org/open_power/control/occ1"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600741 if occ1 == 1:
742 occ1 = 'Active'
743 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600744 occ1 = 'Inactive'
745 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
746 else:
747 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
748 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
749 keylist = ['sensorName', 'type', 'units', 'value', 'target']
Justin Thalere412dc22018-01-12 16:28:24 -0600750
751 return tableDisplay(keylist, colNames, output)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600752 else:
753 return res.text + occres.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600754
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600755def sel(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600756 """
757 prints out the bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600758
Justin Thalere412dc22018-01-12 16:28:24 -0600759 @param host: string, the hostname or IP address of the bmc
760 @param args: contains additional arguments used by the sel sub command
761 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600762 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
763 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600764
765 url="https://"+host+"/xyz/openbmc_project/logging/entry/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600766 try:
Justin Thaler27197622019-01-23 14:42:11 -0600767 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600768 except(requests.exceptions.Timeout):
769 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600770 return res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600771
772
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600773def parseESEL(args, eselRAW):
Justin Thalere412dc22018-01-12 16:28:24 -0600774 """
775 parses the esel data and gets predetermined search terms
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600776
Justin Thalere412dc22018-01-12 16:28:24 -0600777 @param eselRAW: string, the raw esel string from the bmc
778 @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 -0600779 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600780 eselParts = {}
781 esel_bin = binascii.unhexlify(''.join(eselRAW.split()[16:]))
782 #search terms contains the search term as the key and the return dictionary key as it's value
783 searchTerms = { 'Signature Description':'signatureDescription', 'devdesc':'devdesc',
Justin Thaler22b1bb52018-03-15 13:31:32 -0500784 'Callout type': 'calloutType', 'Procedure':'procedure', 'Sensor Type': 'sensorType'}
Justin Thaler24d4efa2018-11-08 22:48:10 -0600785 uniqueID = str(uuid.uuid4())
786 eselBinPath = tempfile.gettempdir() + os.sep + uniqueID + 'esel.bin'
Justin Thalercf1deae2018-05-25 19:35:21 -0500787 with open(eselBinPath, 'wb') as f:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600788 f.write(esel_bin)
789 errlPath = ""
790 #use the right errl file for the machine architecture
791 arch = platform.machine()
792 if(arch =='x86_64' or arch =='AMD64'):
793 if os.path.exists('/opt/ibm/ras/bin/x86_64/errl'):
794 errlPath = '/opt/ibm/ras/bin/x86_64/errl'
795 elif os.path.exists('errl/x86_64/errl'):
796 errlPath = 'errl/x86_64/errl'
797 else:
798 errlPath = 'x86_64/errl'
799 elif (platform.machine()=='ppc64le'):
800 if os.path.exists('/opt/ibm/ras/bin/ppc64le/errl'):
801 errlPath = '/opt/ibm/ras/bin/ppc64le/errl'
802 elif os.path.exists('errl/ppc64le/errl'):
803 errlPath = 'errl/ppc64le/errl'
804 else:
805 errlPath = 'ppc64le/errl'
806 else:
807 print("machine architecture not supported for parsing eSELs")
808 return eselParts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600809
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600810 if(os.path.exists(errlPath)):
Justin Thalercf1deae2018-05-25 19:35:21 -0500811 output= subprocess.check_output([errlPath, '-d', '--file='+eselBinPath]).decode('utf-8')
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600812# output = proc.communicate()[0]
813 lines = output.split('\n')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600814
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600815 if(hasattr(args, 'fullEsel')):
816 return output
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600817
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600818 for i in range(0, len(lines)):
819 lineParts = lines[i].split(':')
820 if(len(lineParts)>1): #ignore multi lines, output formatting lines, and other information
821 for term in searchTerms:
822 if(term in lineParts[0]):
823 temp = lines[i][lines[i].find(':')+1:].strip()[:-1].strip()
824 if lines[i+1].find(':') != -1:
825 if (len(lines[i+1].split(':')[0][1:].strip())==0):
826 while(len(lines[i][:lines[i].find(':')].strip())>2):
Justin Thaler43030422018-11-08 22:50:21 -0600827 #has multiple lines, process and update line counter
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600828 if((i+1) <= len(lines)):
829 i+=1
830 else:
831 i=i-1
832 break
Justin Thaler43030422018-11-08 22:50:21 -0600833 #Append the content from the next line removing the pretty display characters
834 #Finds the first colon then starts 2 characters after, then removes all whitespace
835 temp = temp + lines[i][lines[i].find(':')+2:].strip()[:-1].strip()[:-1].strip()
Justin Thaler22b1bb52018-03-15 13:31:32 -0500836 if(searchTerms[term] in eselParts):
837 eselParts[searchTerms[term]] = eselParts[searchTerms[term]] + ", " + temp
838 else:
839 eselParts[searchTerms[term]] = temp
Justin Thalercf1deae2018-05-25 19:35:21 -0500840 os.remove(eselBinPath)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600841 else:
842 print("errl file cannot be found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600843
844 return eselParts
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600845
Justin Thalere412dc22018-01-12 16:28:24 -0600846
Matt Spinler02d0dff2018-08-29 13:19:25 -0500847def getESELSeverity(esel):
848 """
849 Finds the severity type in an eSEL from the User Header section.
850 @param esel - the eSEL data
851 @return severity - e.g. 'Critical'
852 """
853
854 # everything but 1 and 2 are Critical
855 # '1': 'recovered',
856 # '2': 'predictive',
857 # '4': 'unrecoverable',
858 # '5': 'critical',
859 # '6': 'diagnostic',
860 # '7': 'symptom'
861 severities = {
862 '1': 'Informational',
863 '2': 'Warning'
864 }
865
866 try:
867 headerPosition = esel.index('55 48') # 'UH'
868 # The severity is the last byte in the 8 byte section (a byte is ' bb')
869 severity = esel[headerPosition:headerPosition+32].split(' ')[-1]
870 type = severity[0]
871 except ValueError:
872 print("Could not find severity value in UH section in eSEL")
873 type = 'x';
874
875 return severities.get(type, 'Critical')
876
877
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600878def sortSELs(events):
Justin Thalere412dc22018-01-12 16:28:24 -0600879 """
880 sorts the sels by timestamp, then log entry number
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600881
Justin Thalere412dc22018-01-12 16:28:24 -0600882 @param events: Dictionary containing events
883 @return: list containing a list of the ordered log entries, and dictionary of keys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600884 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600885 logNumList = []
886 timestampList = []
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600887 eventKeyDict = {}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600888 eventsWithTimestamp = {}
889 logNum2events = {}
890 for key in events:
891 if key == 'numAlerts': continue
892 if 'callout' in key: continue
893 timestamp = (events[key]['timestamp'])
894 if timestamp not in timestampList:
895 eventsWithTimestamp[timestamp] = [events[key]['logNum']]
896 else:
897 eventsWithTimestamp[timestamp].append(events[key]['logNum'])
898 #map logNumbers to the event dictionary keys
899 eventKeyDict[str(events[key]['logNum'])] = key
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600900
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600901 timestampList = list(eventsWithTimestamp.keys())
902 timestampList.sort()
903 for ts in timestampList:
904 if len(eventsWithTimestamp[ts]) > 1:
905 tmplist = eventsWithTimestamp[ts]
906 tmplist.sort()
907 logNumList = logNumList + tmplist
908 else:
909 logNumList = logNumList + eventsWithTimestamp[ts]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600910
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600911 return [logNumList, eventKeyDict]
912
Justin Thalere412dc22018-01-12 16:28:24 -0600913
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600914def parseAlerts(policyTable, selEntries, args):
Justin Thalere412dc22018-01-12 16:28:24 -0600915 """
916 parses alerts in the IBM CER format, using an IBM policy Table
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600917
Justin Thalere412dc22018-01-12 16:28:24 -0600918 @param policyTable: dictionary, the policy table entries
919 @param selEntries: dictionary, the alerts retrieved from the bmc
920 @return: A dictionary of the parsed entries, in chronological order
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600921 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600922 eventDict = {}
923 eventNum =""
924 count = 0
925 esel = ""
926 eselParts = {}
927 i2cdevice= ""
Matt Spinler02d0dff2018-08-29 13:19:25 -0500928 eselSeverity = None
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600929
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600930 'prepare and sort the event entries'
Justin Thaler667f87c2020-04-06 16:13:12 -0500931 sels = {}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600932 for key in selEntries:
Justin Thaler667f87c2020-04-06 16:13:12 -0500933 if '/xyz/openbmc_project/logging/entry/' not in key: continue
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600934 if 'callout' not in key:
Justin Thaler667f87c2020-04-06 16:13:12 -0500935 sels[key] = selEntries[key]
936 sels[key]['logNum'] = key.split('/')[-1]
937 sels[key]['timestamp'] = selEntries[key]['Timestamp']
938 sortedEntries = sortSELs(sels)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600939 logNumList = sortedEntries[0]
940 eventKeyDict = sortedEntries[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600941
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600942 for logNum in logNumList:
943 key = eventKeyDict[logNum]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600944 hasEsel=False
945 i2creadFail = False
946 if 'callout' in key:
947 continue
948 else:
949 messageID = str(selEntries[key]['Message'])
950 addDataPiece = selEntries[key]['AdditionalData']
951 calloutIndex = 0
952 calloutFound = False
953 for i in range(len(addDataPiece)):
954 if("CALLOUT_INVENTORY_PATH" in addDataPiece[i]):
955 calloutIndex = i
956 calloutFound = True
957 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
958 if("CALLOUT_DEVICE_PATH" in addDataPiece[i]):
959 i2creadFail = True
Matt Spinlerd178a472018-08-31 09:48:52 -0500960
961 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
962
963 # Fall back to "I2C"/"FSI" if dev path isn't in policy table
964 if (messageID + '||' + fruCallout) not in policyTable:
965 i2cdevice = str(addDataPiece[i]).strip().split('=')[1]
966 i2cdevice = '/'.join(i2cdevice.split('/')[-4:])
967 if 'fsi' in str(addDataPiece[calloutIndex]).split('=')[1]:
968 fruCallout = 'FSI'
969 else:
970 fruCallout = 'I2C'
Justin Thalere34c43a2018-05-25 19:37:55 -0500971 calloutFound = True
972 if("CALLOUT_GPIO_NUM" in addDataPiece[i]):
973 if not calloutFound:
974 fruCallout = 'GPIO'
975 calloutFound = True
976 if("CALLOUT_IIC_BUS" in addDataPiece[i]):
977 if not calloutFound:
978 fruCallout = "I2C"
979 calloutFound = True
980 if("CALLOUT_IPMI_SENSOR_NUM" in addDataPiece[i]):
981 if not calloutFound:
982 fruCallout = "IPMI"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600983 calloutFound = True
984 if("ESEL" in addDataPiece[i]):
985 esel = str(addDataPiece[i]).strip().split('=')[1]
Matt Spinler02d0dff2018-08-29 13:19:25 -0500986 eselSeverity = getESELSeverity(esel)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600987 if args.devdebug:
988 eselParts = parseESEL(args, esel)
989 hasEsel=True
990 if("GPU" in addDataPiece[i]):
991 fruCallout = '/xyz/openbmc_project/inventory/system/chassis/motherboard/gpu' + str(addDataPiece[i]).strip()[-1]
992 calloutFound = True
993 if("PROCEDURE" in addDataPiece[i]):
994 fruCallout = str(hex(int(str(addDataPiece[i]).split('=')[1])))[2:]
995 calloutFound = True
Justin Thalere412dc22018-01-12 16:28:24 -0600996 if("RAIL_NAME" in addDataPiece[i]):
997 calloutFound=True
998 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
999 if("INPUT_NAME" in addDataPiece[i]):
1000 calloutFound=True
1001 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
1002 if("SENSOR_TYPE" in addDataPiece[i]):
1003 calloutFound=True
1004 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001005
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001006 if(calloutFound):
Justin Thaler667f87c2020-04-06 16:13:12 -05001007 if fruCallout.strip() != "":
Justin Thaler22b1bb52018-03-15 13:31:32 -05001008 policyKey = messageID +"||" + fruCallout
Matt Spinler02d0dff2018-08-29 13:19:25 -05001009
1010 # Also use the severity for hostboot errors
1011 if eselSeverity and messageID == 'org.open_power.Host.Error.Event':
1012 policyKey += '||' + eselSeverity
1013
1014 # if not in the table, fall back to the original key
1015 if policyKey not in policyTable:
1016 policyKey = policyKey.replace('||'+eselSeverity, '')
1017
Justin Thalere34c43a2018-05-25 19:37:55 -05001018 if policyKey not in policyTable:
1019 policyKey = messageID
Justin Thaler22b1bb52018-03-15 13:31:32 -05001020 else:
1021 policyKey = messageID
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001022 else:
1023 policyKey = messageID
1024 event = {}
1025 eventNum = str(count)
1026 if policyKey in policyTable:
1027 for pkey in policyTable[policyKey]:
1028 if(type(policyTable[policyKey][pkey])== bool):
1029 event[pkey] = boolToString(policyTable[policyKey][pkey])
1030 else:
1031 if (i2creadFail and pkey == 'Message'):
1032 event[pkey] = policyTable[policyKey][pkey] + ' ' +i2cdevice
1033 else:
1034 event[pkey] = policyTable[policyKey][pkey]
1035 event['timestamp'] = selEntries[key]['Timestamp']
1036 event['resolved'] = bool(selEntries[key]['Resolved'])
1037 if(hasEsel):
1038 if args.devdebug:
1039 event['eselParts'] = eselParts
1040 event['raweSEL'] = esel
1041 event['logNum'] = key.split('/')[-1]
1042 eventDict['event' + eventNum] = event
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001043
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001044 else:
1045 severity = str(selEntries[key]['Severity']).split('.')[-1]
1046 if severity == 'Error':
1047 severity = 'Critical'
1048 eventDict['event'+eventNum] = {}
1049 eventDict['event' + eventNum]['error'] = "error: Not found in policy table: " + policyKey
1050 eventDict['event' + eventNum]['timestamp'] = selEntries[key]['Timestamp']
1051 eventDict['event' + eventNum]['Severity'] = severity
1052 if(hasEsel):
1053 if args.devdebug:
1054 eventDict['event' +eventNum]['eselParts'] = eselParts
1055 eventDict['event' +eventNum]['raweSEL'] = esel
1056 eventDict['event' +eventNum]['logNum'] = key.split('/')[-1]
1057 eventDict['event' +eventNum]['resolved'] = bool(selEntries[key]['Resolved'])
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001058 count += 1
1059 return eventDict
1060
1061
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001062def selDisplay(events, args):
Justin Thalere412dc22018-01-12 16:28:24 -06001063 """
1064 displays alerts in human readable format
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001065
Justin Thalere412dc22018-01-12 16:28:24 -06001066 @param events: Dictionary containing events
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001067 @return:
1068 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001069 activeAlerts = []
1070 historyAlerts = []
1071 sortedEntries = sortSELs(events)
1072 logNumList = sortedEntries[0]
1073 eventKeyDict = sortedEntries[1]
1074 keylist = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message']
1075 if(args.devdebug):
1076 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message', 'eSEL contents']
1077 keylist.append('eSEL')
1078 else:
1079 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity', 'Message']
1080 for log in logNumList:
1081 selDict = {}
1082 alert = events[eventKeyDict[str(log)]]
1083 if('error' in alert):
1084 selDict['Entry'] = alert['logNum']
1085 selDict['ID'] = 'Unknown'
1086 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
1087 msg = alert['error']
1088 polMsg = msg.split("policy table:")[0]
1089 msg = msg.split("policy table:")[1]
1090 msgPieces = msg.split("||")
1091 err = msgPieces[0]
1092 if(err.find("org.open_power.")!=-1):
1093 err = err.split("org.open_power.")[1]
1094 elif(err.find("xyz.openbmc_project.")!=-1):
1095 err = err.split("xyz.openbmc_project.")[1]
1096 else:
1097 err = msgPieces[0]
1098 callout = ""
1099 if len(msgPieces) >1:
1100 callout = msgPieces[1]
1101 if(callout.find("/org/open_power/")!=-1):
1102 callout = callout.split("/org/open_power/")[1]
1103 elif(callout.find("/xyz/openbmc_project/")!=-1):
1104 callout = callout.split("/xyz/openbmc_project/")[1]
1105 else:
1106 callout = msgPieces[1]
1107 selDict['Message'] = polMsg +"policy table: "+ err + "||" + callout
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001108 selDict['Serviceable'] = 'Unknown'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001109 selDict['Severity'] = alert['Severity']
1110 else:
1111 selDict['Entry'] = alert['logNum']
1112 selDict['ID'] = alert['CommonEventID']
1113 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001114 selDict['Message'] = alert['Message']
1115 selDict['Serviceable'] = alert['Serviceable']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001116 selDict['Severity'] = alert['Severity']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001117
1118
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001119 eselOrder = ['refCode','signatureDescription', 'eselType', 'devdesc', 'calloutType', 'procedure']
1120 if ('eselParts' in alert and args.devdebug):
1121 eselOutput = ""
1122 for item in eselOrder:
1123 if item in alert['eselParts']:
1124 eselOutput = eselOutput + item + ": " + alert['eselParts'][item] + " | "
1125 selDict['eSEL'] = eselOutput
1126 else:
1127 if args.devdebug:
1128 selDict['eSEL'] = "None"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001129
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001130 if not alert['resolved']:
1131 activeAlerts.append(selDict)
1132 else:
1133 historyAlerts.append(selDict)
1134 mergedOutput = activeAlerts + historyAlerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001135 colWidth = setColWidth(keylist, len(colNames), dict(enumerate(mergedOutput)), colNames)
1136
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001137 output = ""
1138 if(len(activeAlerts)>0):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001139 row = ""
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001140 output +="----Active Alerts----\n"
1141 for i in range(0, len(colNames)):
1142 if i!=0: row =row + "| "
1143 row = row + colNames[i].ljust(colWidth[i])
1144 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001145
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001146 for i in range(0,len(activeAlerts)):
1147 row = ""
1148 for j in range(len(activeAlerts[i])):
1149 if (j != 0): row = row + "| "
1150 row = row + activeAlerts[i][keylist[j]].ljust(colWidth[j])
1151 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001152
1153 if(len(historyAlerts)>0):
1154 row = ""
1155 output+= "----Historical Alerts----\n"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001156 for i in range(len(colNames)):
1157 if i!=0: row =row + "| "
1158 row = row + colNames[i].ljust(colWidth[i])
1159 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001160
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001161 for i in range(0, len(historyAlerts)):
1162 row = ""
1163 for j in range(len(historyAlerts[i])):
1164 if (j != 0): row = row + "| "
1165 row = row + historyAlerts[i][keylist[j]].ljust(colWidth[j])
1166 output += row + "\n"
1167# print(events[eventKeyDict[str(log)]])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001168 return output
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001169
Justin Thalere412dc22018-01-12 16:28:24 -06001170
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001171def selPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001172 """
1173 prints out all bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001174
Justin Thalere412dc22018-01-12 16:28:24 -06001175 @param host: string, the hostname or IP address of the bmc
1176 @param args: contains additional arguments used by the fru sub command
1177 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001178 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1179 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001180 if(args.policyTableLoc is None):
1181 if os.path.exists('policyTable.json'):
1182 ptableLoc = "policyTable.json"
1183 elif os.path.exists('/opt/ibm/ras/lib/policyTable.json'):
1184 ptableLoc = '/opt/ibm/ras/lib/policyTable.json'
1185 else:
1186 ptableLoc = 'lib/policyTable.json'
1187 else:
1188 ptableLoc = args.policyTableLoc
1189 policyTable = loadPolicyTable(ptableLoc)
1190 rawselEntries = ""
1191 if(hasattr(args, 'fileloc') and args.fileloc is not None):
1192 if os.path.exists(args.fileloc):
1193 with open(args.fileloc, 'r') as selFile:
1194 selLines = selFile.readlines()
1195 rawselEntries = ''.join(selLines)
1196 else:
1197 print("Error: File not found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001198 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001199 else:
1200 rawselEntries = sel(host, args, session)
1201 loadFailed = False
1202 try:
1203 selEntries = json.loads(rawselEntries)
1204 except ValueError:
1205 loadFailed = True
1206 if loadFailed:
1207 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1208 #need to load json twice as original content was string escaped a second time
1209 selEntries = json.loads(json.loads(cleanSels))
1210 selEntries = selEntries['data']
Justin Thalere412dc22018-01-12 16:28:24 -06001211
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001212 if 'description' in selEntries:
1213 if(args.json):
1214 return("{\n\t\"numAlerts\": 0\n}")
1215 else:
1216 return("No log entries found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001217
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001218 else:
1219 if(len(policyTable)>0):
1220 events = parseAlerts(policyTable, selEntries, args)
1221 if(args.json):
1222 events["numAlerts"] = len(events)
1223 retValue = str(json.dumps(events, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
1224 return retValue
1225 elif(hasattr(args, 'fullSel')):
1226 return events
1227 else:
1228 #get log numbers to order event entries sequentially
1229 return selDisplay(events, args)
1230 else:
1231 if(args.json):
1232 return selEntries
1233 else:
1234 print("error: Policy Table not found.")
1235 return selEntries
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001236
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001237def selList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001238 """
1239 prints out all all bmc alerts, or only prints out the specified alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001240
Justin Thalere412dc22018-01-12 16:28:24 -06001241 @param host: string, the hostname or IP address of the bmc
1242 @param args: contains additional arguments used by the fru sub command
1243 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001244 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1245 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001246 return(sel(host, args, session))
1247
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001248
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001249def selClear(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001250 """
1251 clears all alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001252
Justin Thalere412dc22018-01-12 16:28:24 -06001253 @param host: string, the hostname or IP address of the bmc
1254 @param args: contains additional arguments used by the fru sub command
1255 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001256 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1257 """
Matt Spinler47b13e92019-01-04 14:58:53 -06001258 url="https://"+host+"/xyz/openbmc_project/logging/action/DeleteAll"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001259 data = "{\"data\": [] }"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001260
Justin Thalere412dc22018-01-12 16:28:24 -06001261 try:
Justin Thaler27197622019-01-23 14:42:11 -06001262 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001263 except(requests.exceptions.Timeout):
1264 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001265 if res.status_code == 200:
1266 return "The Alert Log has been cleared. Please allow a few minutes for the action to complete."
1267 else:
1268 print("Unable to clear the logs, trying to clear 1 at a time")
1269 sels = json.loads(sel(host, args, session))['data']
1270 for key in sels:
1271 if 'callout' not in key:
1272 logNum = key.split('/')[-1]
1273 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
1274 try:
Justin Thaler27197622019-01-23 14:42:11 -06001275 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001276 except(requests.exceptions.Timeout):
1277 return connectionErrHandler(args.json, "Timeout", None)
1278 sys.exit(1)
1279 except(requests.exceptions.ConnectionError) as err:
1280 return connectionErrHandler(args.json, "ConnectionError", err)
1281 sys.exit(1)
1282 return ('Sel clearing complete')
1283
1284def selSetResolved(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001285 """
1286 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001287
Justin Thalere412dc22018-01-12 16:28:24 -06001288 @param host: string, the hostname or IP address of the bmc
1289 @param args: contains additional arguments used by the fru sub command
1290 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001291 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1292 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001293 url="https://"+host+"/xyz/openbmc_project/logging/entry/" + str(args.selNum) + "/attr/Resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001294 data = "{\"data\": 1 }"
Justin Thalere412dc22018-01-12 16:28:24 -06001295 try:
Justin Thaler27197622019-01-23 14:42:11 -06001296 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001297 except(requests.exceptions.Timeout):
1298 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001299 if res.status_code == 200:
1300 return "Sel entry "+ str(args.selNum) +" is now set to resolved"
1301 else:
1302 return "Unable to set the alert to resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001303
Justin Thalere412dc22018-01-12 16:28:24 -06001304def selResolveAll(host, args, session):
1305 """
1306 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001307
Justin Thalere412dc22018-01-12 16:28:24 -06001308 @param host: string, the hostname or IP address of the bmc
1309 @param args: contains additional arguments used by the fru sub command
1310 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001311 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1312 """
Justin Thalere412dc22018-01-12 16:28:24 -06001313 rawselEntries = sel(host, args, session)
1314 loadFailed = False
1315 try:
1316 selEntries = json.loads(rawselEntries)
1317 except ValueError:
1318 loadFailed = True
1319 if loadFailed:
1320 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1321 #need to load json twice as original content was string escaped a second time
1322 selEntries = json.loads(json.loads(cleanSels))
1323 selEntries = selEntries['data']
1324
1325 if 'description' in selEntries:
1326 if(args.json):
1327 return("{\n\t\"selsResolved\": 0\n}")
1328 else:
1329 return("No log entries found")
1330 else:
1331 d = vars(args)
1332 successlist = []
1333 failedlist = []
1334 for key in selEntries:
1335 if 'callout' not in key:
1336 d['selNum'] = key.split('/')[-1]
1337 resolved = selSetResolved(host,args,session)
1338 if 'Sel entry' in resolved:
1339 successlist.append(d['selNum'])
1340 else:
1341 failedlist.append(d['selNum'])
1342 output = ""
1343 successlist.sort()
1344 failedlist.sort()
1345 if len(successlist)>0:
1346 output = "Successfully resolved: " +', '.join(successlist) +"\n"
1347 if len(failedlist)>0:
1348 output += "Failed to resolve: " + ', '.join(failedlist) + "\n"
1349 return output
1350
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001351def chassisPower(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001352 """
1353 called by the chassis function. Controls the power state of the chassis, or gets the status
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001354
Justin Thalere412dc22018-01-12 16:28:24 -06001355 @param host: string, the hostname or IP address of the bmc
1356 @param args: contains additional arguments used by the fru sub command
1357 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001358 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1359 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001360 if(args.powcmd == 'on'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001361 if checkFWactivation(host, args, session):
1362 return ("Chassis Power control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001363 print("Attempting to Power on...:")
1364 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001365 data = '{"data":"xyz.openbmc_project.State.Host.Transition.On"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001366 try:
Justin Thaler27197622019-01-23 14:42:11 -06001367 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001368 except(requests.exceptions.Timeout):
1369 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001370 return res.text
Justin Thalere412dc22018-01-12 16:28:24 -06001371 elif(args.powcmd == 'softoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001372 if checkFWactivation(host, args, session):
1373 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001374 print("Attempting to Power off gracefully...:")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001375 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001376 data = '{"data":"xyz.openbmc_project.State.Host.Transition.Off"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001377 try:
Justin Thaler27197622019-01-23 14:42:11 -06001378 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001379 except(requests.exceptions.Timeout):
1380 return(connectionErrHandler(args.json, "Timeout", None))
1381 return res.text
1382 elif(args.powcmd == 'hardoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001383 if checkFWactivation(host, args, session):
1384 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001385 print("Attempting to Power off immediately...:")
1386 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06001387 data = '{"data":"xyz.openbmc_project.State.Chassis.Transition.Off"}'
1388 try:
Justin Thaler27197622019-01-23 14:42:11 -06001389 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001390 except(requests.exceptions.Timeout):
1391 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001392 return res.text
1393 elif(args.powcmd == 'status'):
1394 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState"
Justin Thalere412dc22018-01-12 16:28:24 -06001395 try:
Justin Thaler27197622019-01-23 14:42:11 -06001396 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001397 except(requests.exceptions.Timeout):
1398 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001399 chassisState = json.loads(res.text)['data'].split('.')[-1]
1400 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/CurrentHostState"
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 hostState = json.loads(res.text)['data'].split('.')[-1]
1406 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/CurrentBMCState"
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 bmcState = json.loads(res.text)['data'].split('.')[-1]
1412 if(args.json):
1413 outDict = {"Chassis Power State" : chassisState, "Host Power State" : hostState, "BMC Power State":bmcState}
1414 return json.dumps(outDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
1415 else:
1416 return "Chassis Power State: " +chassisState + "\nHost Power State: " + hostState + "\nBMC Power State: " + bmcState
1417 else:
1418 return "Invalid chassis power command"
1419
Justin Thalere412dc22018-01-12 16:28:24 -06001420
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001421def chassisIdent(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001422 """
1423 called by the chassis function. Controls the identify led of the chassis. Sets or gets the state
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001424
Justin Thalere412dc22018-01-12 16:28:24 -06001425 @param host: string, the hostname or IP address of the bmc
1426 @param args: contains additional arguments used by the fru sub command
1427 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001428 @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 -06001429 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001430 if(args.identcmd == 'on'):
1431 print("Attempting to turn identify light on...:")
1432 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001433 data = '{"data":true}'
Justin Thalere412dc22018-01-12 16:28:24 -06001434 try:
Justin Thaler27197622019-01-23 14:42:11 -06001435 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001436 except(requests.exceptions.Timeout):
1437 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001438 return res.text
1439 elif(args.identcmd == 'off'):
1440 print("Attempting to turn identify light off...:")
1441 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001442 data = '{"data":false}'
Justin Thalere412dc22018-01-12 16:28:24 -06001443 try:
Justin Thaler27197622019-01-23 14:42:11 -06001444 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001445 except(requests.exceptions.Timeout):
1446 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001447 return res.text
1448 elif(args.identcmd == 'status'):
1449 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify"
Justin Thalere412dc22018-01-12 16:28:24 -06001450 try:
Justin Thaler27197622019-01-23 14:42:11 -06001451 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001452 except(requests.exceptions.Timeout):
1453 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001454 status = json.loads(res.text)['data']
1455 if(args.json):
1456 return status
1457 else:
1458 if status['Asserted'] == 0:
1459 return "Identify light is off"
1460 else:
1461 return "Identify light is blinking"
1462 else:
1463 return "Invalid chassis identify command"
1464
Justin Thalere412dc22018-01-12 16:28:24 -06001465
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001466def chassis(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001467 """
1468 controls the different chassis commands
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001469
Justin Thalere412dc22018-01-12 16:28:24 -06001470 @param host: string, the hostname or IP address of the bmc
1471 @param args: contains additional arguments used by the fru sub command
1472 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001473 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1474 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001475 if(hasattr(args, 'powcmd')):
1476 result = chassisPower(host,args,session)
1477 elif(hasattr(args, 'identcmd')):
1478 result = chassisIdent(host, args, session)
1479 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001480 return "This feature is not yet implemented"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001481 return result
Justin Thalere412dc22018-01-12 16:28:24 -06001482
Ravi Tejad8be0b42020-03-18 14:31:46 -05001483def dumpRetrieve(host, args, session):
1484 """
1485 Downloads dump of given dump type
1486
1487 @param host: string, the hostname or IP address of the bmc
1488 @param args: contains additional arguments used by the collectServiceData sub command
1489 @param session: the active session to use
1490 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1491 """
1492 dumpType = args.dumpType
1493 if (args.dumpType=="SystemDump"):
1494 dumpResp=systemDumpRetrieve(host,args,session)
1495 elif(args.dumpType=="bmc"):
1496 dumpResp=bmcDumpRetrieve(host,args,session)
1497 return dumpResp
1498
1499def dumpList(host, args, session):
1500 """
1501 Lists dump of the given dump type
1502
1503 @param host: string, the hostname or IP address of the bmc
1504 @param args: contains additional arguments used by the collectServiceData sub command
1505 @param session: the active session to use
1506 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1507 """
1508 if (args.dumpType=="SystemDump"):
1509 dumpResp=systemDumpList(host,args,session)
1510 elif(args.dumpType=="bmc"):
1511 dumpResp=bmcDumpList(host,args,session)
1512 return dumpResp
1513
1514def dumpDelete(host, args, session):
1515 """
1516 Deletes dump of the given dump type
1517
1518 @param host: string, the hostname or IP address of the bmc
1519 @param args: contains additional arguments used by the collectServiceData sub command
1520 @param session: the active session to use
1521 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1522 """
1523 if (args.dumpType=="SystemDump"):
1524 dumpResp=systemDumpDelete(host,args,session)
1525 elif(args.dumpType=="bmc"):
1526 dumpResp=bmcDumpDelete(host,args,session)
1527 return dumpResp
1528
1529def dumpDeleteAll(host, args, session):
1530 """
1531 Deletes all dumps of the given dump type
1532
1533 @param host: string, the hostname or IP address of the bmc
1534 @param args: contains additional arguments used by the collectServiceData sub command
1535 @param session: the active session to use
1536 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1537 """
1538 if (args.dumpType=="SystemDump"):
1539 dumpResp=systemDumpDeleteAll(host,args,session)
1540 elif(args.dumpType=="bmc"):
1541 dumpResp=bmcDumpDeleteAll(host,args,session)
1542 return dumpResp
1543
1544def dumpCreate(host, args, session):
1545 """
1546 Creates dump for the given dump type
1547
1548 @param host: string, the hostname or IP address of the bmc
1549 @param args: contains additional arguments used by the collectServiceData sub command
1550 @param session: the active session to use
1551 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1552 """
1553 if (args.dumpType=="SystemDump"):
1554 dumpResp=systemDumpCreate(host,args,session)
1555 elif(args.dumpType=="bmc"):
Justin Thaler0a3e1692020-04-07 19:10:40 -05001556 dumpResp=bmcDumpCreate(host,args,session)
Ravi Tejad8be0b42020-03-18 14:31:46 -05001557 return dumpResp
1558
1559
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001560def bmcDumpRetrieve(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001561 """
1562 Downloads a dump file from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001563
Justin Thalere412dc22018-01-12 16:28:24 -06001564 @param host: string, the hostname or IP address of the bmc
1565 @param args: contains additional arguments used by the collectServiceData sub command
1566 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001567 @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 -06001568 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001569 dumpNum = args.dumpNum
1570 if (args.dumpSaveLoc is not None):
1571 saveLoc = args.dumpSaveLoc
1572 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001573 saveLoc = tempfile.gettempdir()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001574 url ='https://'+host+'/download/dump/' + str(dumpNum)
1575 try:
Justin Thaler27197622019-01-23 14:42:11 -06001576 r = session.get(url, headers=jsonHeader, stream=True, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001577 if (args.dumpSaveLoc is not None):
1578 if os.path.exists(saveLoc):
1579 if saveLoc[-1] != os.path.sep:
1580 saveLoc = saveLoc + os.path.sep
1581 filename = saveLoc + host+'-dump' + str(dumpNum) + '.tar.xz'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001582
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001583 else:
1584 return 'Invalid save location specified'
1585 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001586 filename = tempfile.gettempdir()+os.sep + host+'-dump' + str(dumpNum) + '.tar.xz'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001587
1588 with open(filename, 'wb') as f:
1589 for chunk in r.iter_content(chunk_size =1024):
1590 if chunk:
1591 f.write(chunk)
1592 return 'Saved as ' + filename
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001593
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001594 except(requests.exceptions.Timeout):
1595 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001596
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001597 except(requests.exceptions.ConnectionError) as err:
1598 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001599
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001600def bmcDumpList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001601 """
1602 Lists the number of dump files on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001603
Justin Thalere412dc22018-01-12 16:28:24 -06001604 @param host: string, the hostname or IP address of the bmc
1605 @param args: contains additional arguments used by the collectServiceData sub command
1606 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001607 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1608 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001609 url ='https://'+host+'/xyz/openbmc_project/dump/list'
1610 try:
Justin Thaler27197622019-01-23 14:42:11 -06001611 r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3a5771b2019-01-23 14:31:52 -06001612 dumpList = r.json()
Justin Thaler3b3c6582020-04-07 19:17:36 -05001613 formattedList = []
1614 #remove items that aren't dump entries 'entry, internal, manager endpoints'
1615 if 'data' in dumpList:
1616 for entry in dumpList['data']:
1617 if 'entry' in entry:
1618 if entry.split('/')[-1].isnumeric():
1619 formattedList.append(entry)
1620 dumpList['data']= formattedList
Justin Thaler3a5771b2019-01-23 14:31:52 -06001621 return dumpList
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001622 except(requests.exceptions.Timeout):
1623 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001624
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001625 except(requests.exceptions.ConnectionError) as err:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001626 return connectionErrHandler(args.json, "ConnectionError", err)
1627
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001628def bmcDumpDelete(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001629 """
1630 Deletes BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001631
Justin Thalere412dc22018-01-12 16:28:24 -06001632 @param host: string, the hostname or IP address of the bmc
1633 @param args: contains additional arguments used by the collectServiceData sub command
1634 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001635 @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 -06001636 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001637 dumpList = []
1638 successList = []
1639 failedList = []
1640 if args.dumpNum is not None:
1641 if isinstance(args.dumpNum, list):
1642 dumpList = args.dumpNum
1643 else:
1644 dumpList.append(args.dumpNum)
1645 for dumpNum in dumpList:
1646 url ='https://'+host+'/xyz/openbmc_project/dump/entry/'+str(dumpNum)+'/action/Delete'
1647 try:
Justin Thaler27197622019-01-23 14:42:11 -06001648 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001649 if r.status_code == 200:
1650 successList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001651 else:
1652 failedList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001653 except(requests.exceptions.Timeout):
1654 return connectionErrHandler(args.json, "Timeout", None)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001655 except(requests.exceptions.ConnectionError) as err:
1656 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001657 output = "Successfully deleted dumps: " + ', '.join(successList)
1658 if(len(failedList)>0):
1659 output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
1660 return output
1661 else:
1662 return 'You must specify an entry number to delete'
1663
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001664def bmcDumpDeleteAll(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001665 """
1666 Deletes All BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001667
Justin Thalere412dc22018-01-12 16:28:24 -06001668 @param host: string, the hostname or IP address of the bmc
1669 @param args: contains additional arguments used by the collectServiceData sub command
1670 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001671 @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 -06001672 """
1673 dumpResp = bmcDumpList(host, args, session)
1674 if 'FQPSPIN0000M' in dumpResp or 'FQPSPIN0001M'in dumpResp:
1675 return dumpResp
Justin Thaler3a5771b2019-01-23 14:31:52 -06001676 dumpList = dumpResp['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001677 d = vars(args)
1678 dumpNums = []
1679 for dump in dumpList:
Alvin Wang28bd09d2019-10-28 13:23:58 +08001680 dumpNum = dump.strip().split('/')[-1]
1681 if dumpNum.isdigit():
1682 dumpNums.append(int(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001683 d['dumpNum'] = dumpNums
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001684
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001685 return bmcDumpDelete(host, args, session)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001686
Justin Thalere412dc22018-01-12 16:28:24 -06001687
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001688def bmcDumpCreate(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001689 """
1690 Creates a bmc dump file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001691
Justin Thalere412dc22018-01-12 16:28:24 -06001692 @param host: string, the hostname or IP address of the bmc
1693 @param args: contains additional arguments used by the collectServiceData sub command
1694 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001695 @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 -06001696 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001697 url = 'https://'+host+'/xyz/openbmc_project/dump/action/CreateDump'
1698 try:
Justin Thaler27197622019-01-23 14:42:11 -06001699 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Justin Thaler2f59aea2020-04-07 19:27:01 -05001700 info = r.json()
Matt Spinlereae05b02019-01-24 12:59:34 -06001701 if(r.status_code == 200 and not args.json):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001702 return ('Dump successfully created')
Justin Thaler3a5771b2019-01-23 14:31:52 -06001703 elif(args.json):
Justin Thaler2f59aea2020-04-07 19:27:01 -05001704 return info
1705 elif 'data' in info:
1706 if 'QuotaExceeded' in info['data']['description']:
1707 return 'BMC dump space is full. Please delete at least one existing dump entry and try again.'
1708 else:
1709 return "Failed to create a BMC dump. BMC Response:\n {resp}".format(resp=info)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001710 else:
Justin Thaler2f59aea2020-04-07 19:27:01 -05001711 return "Failed to create a BMC dump. BMC Response:\n {resp}".format(resp=info)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001712 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
Justin Thaler2f59aea2020-04-07 19:27:01 -05001717
Ravi Tejad8be0b42020-03-18 14:31:46 -05001718def systemDumpRetrieve(host, args, session):
1719 """
1720 Downloads system dump
1721
1722 @param host: string, the hostname or IP address of the bmc
1723 @param args: contains additional arguments used by the collectServiceData sub command
1724 @param session: the active session to use
1725 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1726 """
1727 NBDSetup(host,args,session)
1728 pipe = NBDPipe()
1729 pipe.openHTTPSocket(args)
1730 pipe.openTCPSocket()
1731 pipe.waitformessage()
1732
1733def systemDumpList(host, args, session):
1734 """
1735 Lists system dumps
1736
1737 @param host: string, the hostname or IP address of the bmc
1738 @param args: contains additional arguments used by the collectServiceData sub command
1739 @param session: the active session to use
1740 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1741 """
1742 print("in systemDumpList")
1743 url = "https://"+host+"/redfish/v1/Systems/system/LogServices/"+args.dumpType+"/Entries"
1744 try:
1745 r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
1746 dumpList = r.json()
1747 return dumpList
1748 except(requests.exceptions.Timeout):
1749 return connectionErrHandler(args.json, "Timeout", None)
1750
1751 except(requests.exceptions.ConnectionError) as err:
1752 return connectionErrHandler(args.json, "ConnectionError", err)
1753
1754
1755def systemDumpDelete(host, args, session):
1756 """
1757 Deletes system dump
1758
1759 @param host: string, the hostname or IP address of the bmc
1760 @param args: contains additional arguments used by the collectServiceData sub command
1761 @param session: the active session to use
1762 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1763 """
1764 dumpList = []
1765 successList = []
1766 failedList = []
1767 if args.dumpNum is not None:
1768 if isinstance(args.dumpNum, list):
1769 dumpList = args.dumpNum
1770 else:
1771 dumpList.append(args.dumpNum)
1772 for dumpNum in dumpList:
1773 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/'+args.dumpType+'/Entries/'+ str(dumpNum)
1774 try:
1775 r = session.delete(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1776 if r.status_code == 200:
1777 successList.append(str(dumpNum))
1778 else:
1779 failedList.append(str(dumpNum))
1780 except(requests.exceptions.Timeout):
1781 return connectionErrHandler(args.json, "Timeout", None)
1782 except(requests.exceptions.ConnectionError) as err:
1783 return connectionErrHandler(args.json, "ConnectionError", err)
1784 output = "Successfully deleted dumps: " + ', '.join(successList)
1785 if(len(failedList)>0):
1786 output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
1787 return output
1788 else:
1789 return 'You must specify an entry number to delete'
1790
1791def systemDumpDeleteAll(host, args, session):
1792 """
1793 Deletes All system dumps
1794
1795 @param host: string, the hostname or IP address of the bmc
1796 @param args: contains additional arguments used by the collectServiceData sub command
1797 @param session: the active session to use
1798 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1799 """
1800 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/'+args.dumpType+'/Actions/LogService.ClearLog'
1801 try:
1802 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1803 if(r.status_code == 200 and not args.json):
1804 return ('Dumps successfully cleared')
1805 elif(args.json):
1806 return r.json()
1807 else:
1808 return ('Failed to clear dumps')
1809 except(requests.exceptions.Timeout):
1810 return connectionErrHandler(args.json, "Timeout", None)
1811 except(requests.exceptions.ConnectionError) as err:
1812 return connectionErrHandler(args.json, "ConnectionError", err)
1813
1814def systemDumpCreate(host, args, session):
1815 """
1816 Creates a system dump
1817
1818 @param host: string, the hostname or IP address of the bmc
1819 @param args: contains additional arguments used by the collectServiceData sub command
1820 @param session: the active session to use
1821 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1822 """
1823 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/'+args.dumpType+'/Actions/Oem/Openbmc/LogService.CreateLog'
1824 try:
1825 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1826 if(r.status_code == 200 and not args.json):
1827 return ('Dump successfully created')
1828 elif(args.json):
1829 return r.json()
1830 else:
1831 return ('Failed to create dump')
1832 except(requests.exceptions.Timeout):
1833 return connectionErrHandler(args.json, "Timeout", None)
1834 except(requests.exceptions.ConnectionError) as err:
1835 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001836
Justin Thaler666cf342019-01-23 14:44:27 -06001837def csdDumpInitiate(host, args, session):
1838 """
1839 Starts the process of getting the current list of dumps then initiates the creation of one.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001840
Justin Thaler666cf342019-01-23 14:44:27 -06001841 @param host: string, the hostname or IP address of the bmc
1842 @param args: contains additional arguments used by the collectServiceData sub command
1843 @param session: the active session to use
1844 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1845 """
1846 errorInfo = ""
1847 dumpcount = 0
1848 try:
1849 d = vars(args)
1850 d['json'] = True
1851 except Exception as e:
1852 errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001853 exc_type, exc_obj, exc_tb = sys.exc_info()
1854 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1855 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1856 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001857
1858 try:
1859 for i in range(3):
1860 dumpInfo = bmcDumpList(host, args, session)
1861 if 'data' in dumpInfo:
1862 dumpcount = len(dumpInfo['data'])
1863 break
1864 else:
1865 errorInfo+= "Dump List Message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n"
1866 except Exception as e:
1867 errorInfo+= "Failed to collect the list of dumps.\nException: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001868 exc_type, exc_obj, exc_tb = sys.exc_info()
1869 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1870 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1871 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001872
1873 #Create a user initiated dump
Justin Thalerb4256672020-04-07 19:38:26 -05001874 dumpFailure = True
Justin Thaler666cf342019-01-23 14:44:27 -06001875 try:
1876 for i in range(3):
1877 dumpcreated = bmcDumpCreate(host, args, session)
1878 if 'message' in dumpcreated:
1879 if 'ok' in dumpcreated['message'].lower():
Justin Thalerb4256672020-04-07 19:38:26 -05001880 dumpFailure = False
Justin Thaler666cf342019-01-23 14:44:27 -06001881 break
Justin Thalerb4256672020-04-07 19:38:26 -05001882 elif 'data' in dumpcreated:
1883 if 'QuotaExceeded' in dumpcreated['data']['description']:
1884 print('Not enough dump space on the BMC to create a new dump. Please delete the oldest entry (lowest number) and rerun the collect_service_data command.')
1885 errorInfo+='Dump Space is full. No new dump was created with this collection'
1886 break
1887 else:
1888 errorInfo+= "Dump create message returned: " + json.dumps(dumpcreated,indent=0, separators=(',', ':')).replace('\n','') +"\n"
Justin Thaler666cf342019-01-23 14:44:27 -06001889 else:
Justin Thalerb4256672020-04-07 19:38:26 -05001890 errorInfo+= "Dump create message returned: " + json.dumps(dumpcreated,indent=0, separators=(',', ':')).replace('\n','') +"\n"
Justin Thaler666cf342019-01-23 14:44:27 -06001891 else:
Justin Thalerb4256672020-04-07 19:38:26 -05001892 errorInfo+= "Dump create message returned: " + json.dumps(dumpcreated,indent=0, separators=(',', ':')).replace('\n','') +"\n"
Justin Thaler666cf342019-01-23 14:44:27 -06001893 except Exception as e:
1894 errorInfo+= "Dump create exception encountered: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001895 exc_type, exc_obj, exc_tb = sys.exc_info()
1896 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1897 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1898 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001899
1900 output = {}
1901 output['errors'] = errorInfo
1902 output['dumpcount'] = dumpcount
Justin Thalerb4256672020-04-07 19:38:26 -05001903 if dumpFailure: output['dumpFailure'] = True
Justin Thaler666cf342019-01-23 14:44:27 -06001904 return output
1905
1906def csdInventory(host, args,session, fileDir):
1907 """
1908 Collects the BMC inventory, retrying if necessary
1909
1910 @param host: string, the hostname or IP address of the bmc
1911 @param args: contains additional arguments used by the collectServiceData sub command
1912 @param session: the active session to use
1913 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1914 @param fileDir: string representation of the path to use for putting files created
1915 """
1916 errorInfo = "===========Inventory =============\n"
1917 output={}
1918 inventoryCollected = False
1919 try:
1920 for i in range(3):
1921 frulist = fruPrint(host, args, session)
1922 if 'Hardware' in frulist:
1923 inventoryCollected = True
1924 break
1925 else:
1926 errorInfo += json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1927 except Exception as e:
1928 errorInfo += "Inventory collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001929 exc_type, exc_obj, exc_tb = sys.exc_info()
1930 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1931 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1932 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001933 if inventoryCollected:
1934 try:
1935 with open(fileDir +os.sep+'inventory.txt', 'w') as f:
1936 f.write(json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
1937 print("Inventory collected and stored in " + fileDir + os.sep + "inventory.txt")
1938 output['fileLoc'] = fileDir+os.sep+'inventory.txt'
1939 except Exception as e:
1940 print("Failed to write inventory to file.")
1941 errorInfo += "Error writing inventory to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001942 exc_type, exc_obj, exc_tb = sys.exc_info()
1943 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1944 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1945 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001946
1947 output['errors'] = errorInfo
1948
1949 return output
1950
1951def csdSensors(host, args,session, fileDir):
1952 """
1953 Collects the BMC sensor readings, retrying if necessary
1954
1955 @param host: string, the hostname or IP address of the bmc
1956 @param args: contains additional arguments used by the collectServiceData sub command
1957 @param session: the active session to use
1958 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1959 @param fileDir: string representation of the path to use for putting files created
1960 """
1961 errorInfo = "===========Sensors =============\n"
1962 sensorsCollected = False
1963 output={}
1964 try:
1965 d = vars(args)
1966 d['json'] = False
1967 except Exception as e:
1968 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001969 exc_type, exc_obj, exc_tb = sys.exc_info()
1970 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1971 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1972 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001973
1974 try:
1975 for i in range(3):
1976 sensorReadings = sensor(host, args, session)
1977 if 'OCC0' in sensorReadings:
1978 sensorsCollected = True
1979 break
1980 else:
1981 errorInfo += sensorReadings
1982 except Exception as e:
1983 errorInfo += "Sensor reading collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001984 exc_type, exc_obj, exc_tb = sys.exc_info()
1985 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1986 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
1987 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06001988 if sensorsCollected:
1989 try:
1990 with open(fileDir +os.sep+'sensorReadings.txt', 'w') as f:
1991 f.write(sensorReadings)
1992 print("Sensor readings collected and stored in " + fileDir + os.sep+ "sensorReadings.txt")
1993 output['fileLoc'] = fileDir+os.sep+'sensorReadings.txt'
1994 except Exception as e:
1995 print("Failed to write sensor readings to file system.")
1996 errorInfo += "Error writing sensor readings to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05001997 exc_type, exc_obj, exc_tb = sys.exc_info()
1998 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
1999 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2000 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002001
2002 output['errors'] = errorInfo
2003 return output
2004
2005def csdLEDs(host,args, session, fileDir):
2006 """
2007 Collects the BMC LED status, retrying if necessary
2008
2009 @param host: string, the hostname or IP address of the bmc
2010 @param args: contains additional arguments used by the collectServiceData sub command
2011 @param session: the active session to use
2012 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2013 @param fileDir: string representation of the path to use for putting files created
2014 """
2015 errorInfo = "===========LEDs =============\n"
2016 ledsCollected = False
2017 output={}
2018 try:
2019 d = vars(args)
2020 d['json'] = True
2021 except Exception as e:
2022 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002023 exc_type, exc_obj, exc_tb = sys.exc_info()
2024 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2025 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2026 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002027 try:
2028 url="https://"+host+"/xyz/openbmc_project/led/enumerate"
2029 httpHeader = {'Content-Type':'application/json'}
2030 for i in range(3):
2031 try:
2032 ledRes = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
2033 if ledRes.status_code == 200:
2034 ledsCollected = True
2035 leds = ledRes.json()['data']
2036 break
2037 else:
2038 errorInfo += ledRes.text
2039 except(requests.exceptions.Timeout):
2040 errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
2041 except(requests.exceptions.ConnectionError) as err:
2042 errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
Justin Thalerb4256672020-04-07 19:38:26 -05002043 exc_type, exc_obj, exc_tb = sys.exc_info()
2044 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2045 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2046 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002047 except Exception as e:
2048 errorInfo += "LED status collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002049 exc_type, exc_obj, exc_tb = sys.exc_info()
2050 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2051 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2052 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002053
2054 if ledsCollected:
2055 try:
2056 with open(fileDir +os.sep+'ledStatus.txt', 'w') as f:
2057 f.write(json.dumps(leds, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
2058 print("LED status collected and stored in " + fileDir + os.sep+ "ledStatus.txt")
2059 output['fileLoc'] = fileDir+os.sep+'ledStatus.txt'
2060 except Exception as e:
2061 print("Failed to write LED status to file system.")
2062 errorInfo += "Error writing LED status to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002063 exc_type, exc_obj, exc_tb = sys.exc_info()
2064 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2065 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2066 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002067
2068 output['errors'] = errorInfo
2069 return output
2070
2071def csdSelShortList(host, args, session, fileDir):
2072 """
2073 Collects the BMC log entries, retrying if necessary
2074
2075 @param host: string, the hostname or IP address of the bmc
2076 @param args: contains additional arguments used by the collectServiceData sub command
2077 @param session: the active session to use
2078 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2079 @param fileDir: string representation of the path to use for putting files created
2080 """
2081 errorInfo = "===========SEL Short List =============\n"
2082 selsCollected = False
2083 output={}
2084 try:
2085 d = vars(args)
2086 d['json'] = False
2087 except Exception as e:
2088 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002089 exc_type, exc_obj, exc_tb = sys.exc_info()
2090 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2091 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2092 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002093
2094 try:
2095 for i in range(3):
2096 sels = selPrint(host,args,session)
2097 if '----Active Alerts----' in sels or 'No log entries found' in sels or '----Historical Alerts----' in sels:
2098 selsCollected = True
2099 break
2100 else:
2101 errorInfo += sels + '\n'
2102 except Exception as e:
2103 errorInfo += "SEL short list collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002104 exc_type, exc_obj, exc_tb = sys.exc_info()
2105 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2106 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2107 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002108
2109 if selsCollected:
2110 try:
2111 with open(fileDir +os.sep+'SELshortlist.txt', 'w') as f:
2112 f.write(sels)
2113 print("SEL short list collected and stored in " + fileDir + os.sep+ "SELshortlist.txt")
2114 output['fileLoc'] = fileDir+os.sep+'SELshortlist.txt'
2115 except Exception as e:
2116 print("Failed to write SEL short list to file system.")
2117 errorInfo += "Error writing SEL short list to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002118 exc_type, exc_obj, exc_tb = sys.exc_info()
2119 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2120 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2121 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002122
2123 output['errors'] = errorInfo
2124 return output
2125
2126def csdParsedSels(host, args, session, fileDir):
2127 """
2128 Collects the BMC log entries, retrying if necessary
2129
2130 @param host: string, the hostname or IP address of the bmc
2131 @param args: contains additional arguments used by the collectServiceData sub command
2132 @param session: the active session to use
2133 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2134 @param fileDir: string representation of the path to use for putting files created
2135 """
2136 errorInfo = "===========SEL Parsed List =============\n"
2137 selsCollected = False
2138 output={}
2139 try:
2140 d = vars(args)
2141 d['json'] = True
2142 d['fullEsel'] = True
2143 except Exception as e:
2144 errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002145 exc_type, exc_obj, exc_tb = sys.exc_info()
2146 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2147 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2148 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002149
2150 try:
2151 for i in range(3):
2152 parsedfullsels = json.loads(selPrint(host,args,session))
2153 if 'numAlerts' in parsedfullsels:
2154 selsCollected = True
2155 break
2156 else:
2157 errorInfo += parsedfullsels + '\n'
2158 except Exception as e:
2159 errorInfo += "Parsed full SELs collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002160 exc_type, exc_obj, exc_tb = sys.exc_info()
2161 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2162 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2163 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002164
2165 if selsCollected:
2166 try:
2167 sortedSELs = sortSELs(parsedfullsels)
2168 with open(fileDir +os.sep+'parsedSELs.txt', 'w') as f:
2169 for log in sortedSELs[0]:
2170 esel = ""
2171 parsedfullsels[sortedSELs[1][str(log)]]['timestamp'] = datetime.datetime.fromtimestamp(int(parsedfullsels[sortedSELs[1][str(log)]]['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
2172 if ('raweSEL' in parsedfullsels[sortedSELs[1][str(log)]] and args.devdebug):
2173 esel = parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
2174 del parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
2175 f.write(json.dumps(parsedfullsels[sortedSELs[1][str(log)]],sort_keys=True, indent=4, separators=(',', ': ')))
2176 if(args.devdebug and esel != ""):
2177 f.write(parseESEL(args, esel))
2178 print("Parsed SELs collected and stored in " + fileDir + os.sep+ "parsedSELs.txt")
2179 output['fileLoc'] = fileDir+os.sep+'parsedSELs.txt'
2180 except Exception as e:
2181 print("Failed to write fully parsed SELs to file system.")
2182 errorInfo += "Error writing fully parsed SELs to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002183 exc_type, exc_obj, exc_tb = sys.exc_info()
2184 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2185 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2186 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002187
2188 output['errors'] = errorInfo
2189 return output
2190
2191def csdFullEnumeration(host, args, session, fileDir):
2192 """
2193 Collects a full enumeration of /xyz/openbmc_project/, retrying if necessary
2194
2195 @param host: string, the hostname or IP address of the bmc
2196 @param args: contains additional arguments used by the collectServiceData sub command
2197 @param session: the active session to use
2198 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2199 @param fileDir: string representation of the path to use for putting files created
2200 """
2201 errorInfo = "===========BMC Full Enumeration =============\n"
2202 bmcFullCollected = False
2203 output={}
2204 try:
2205 d = vars(args)
2206 d['json'] = True
2207 except Exception as e:
2208 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002209 exc_type, exc_obj, exc_tb = sys.exc_info()
2210 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2211 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2212 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002213 try:
2214 print("Attempting to get a full BMC enumeration")
2215 url="https://"+host+"/xyz/openbmc_project/enumerate"
2216 httpHeader = {'Content-Type':'application/json'}
2217 for i in range(3):
2218 try:
2219 bmcRes = session.get(url, headers=jsonHeader, verify=False, timeout=180)
2220 if bmcRes.status_code == 200:
2221 bmcFullCollected = True
2222 fullEnumeration = bmcRes.json()
2223 break
2224 else:
2225 errorInfo += bmcRes.text
2226 except(requests.exceptions.Timeout):
2227 errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
2228 except(requests.exceptions.ConnectionError) as err:
2229 errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
Justin Thalerb4256672020-04-07 19:38:26 -05002230 exc_type, exc_obj, exc_tb = sys.exc_info()
2231 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2232 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2233 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002234 except Exception as e:
2235 errorInfo += "RAW BMC data collection exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002236 exc_type, exc_obj, exc_tb = sys.exc_info()
2237 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2238 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2239 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002240
2241 if bmcFullCollected:
2242 try:
2243 with open(fileDir +os.sep+'bmcFullRaw.txt', 'w') as f:
2244 f.write(json.dumps(fullEnumeration, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
2245 print("RAW BMC data collected and saved into " + fileDir + os.sep+ "bmcFullRaw.txt")
2246 output['fileLoc'] = fileDir+os.sep+'bmcFullRaw.txt'
2247 except Exception as e:
2248 print("Failed to write RAW BMC data to file system.")
2249 errorInfo += "Error writing RAW BMC data collection to the file. Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002250 exc_type, exc_obj, exc_tb = sys.exc_info()
2251 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2252 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2253 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002254
2255 output['errors'] = errorInfo
2256 return output
2257
2258def csdCollectAllDumps(host, args, session, fileDir):
2259 """
2260 Collects all of the bmc dump files and stores them in fileDir
2261
2262 @param host: string, the hostname or IP address of the bmc
2263 @param args: contains additional arguments used by the collectServiceData sub command
2264 @param session: the active session to use
2265 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2266 @param fileDir: string representation of the path to use for putting files created
2267 """
2268
2269 errorInfo = "===========BMC Dump Collection =============\n"
2270 dumpListCollected = False
2271 output={}
2272 dumpList = {}
2273 try:
2274 d = vars(args)
2275 d['json'] = True
2276 d['dumpSaveLoc'] = fileDir
2277 except Exception as e:
2278 errorInfo += "Failed to set the json flag to True, or failed to set the dumpSave Location \n Exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002279 exc_type, exc_obj, exc_tb = sys.exc_info()
2280 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2281 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2282 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002283
2284 print('Collecting bmc dump files')
2285
2286 try:
2287 for i in range(3):
2288 dumpResp = bmcDumpList(host, args, session)
2289 if 'message' in dumpResp:
2290 if 'ok' in dumpResp['message'].lower():
2291 dumpList = dumpResp['data']
2292 dumpListCollected = True
2293 break
2294 else:
2295 errorInfo += "Status was not OK when retrieving the list of dumps available. \n Response: \n{resp}\n".format(resp=dumpResp)
2296 else:
2297 errorInfo += "Invalid response received from the BMC while retrieving the list of dumps available.\n {resp}\n".format(resp=dumpResp)
2298 except Exception as e:
2299 errorInfo += "BMC dump list exception: {eInfo}\n".format(eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002300 exc_type, exc_obj, exc_tb = sys.exc_info()
2301 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2302 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2303 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002304
2305 if dumpListCollected:
2306 output['fileList'] = []
2307 for dump in dumpList:
2308 try:
2309 if '/xyz/openbmc_project/dump/internal/manager' not in dump:
2310 d['dumpNum'] = int(dump.strip().split('/')[-1])
2311 print('retrieving dump file ' + str(d['dumpNum']))
2312 filename = bmcDumpRetrieve(host, args, session).split('Saved as ')[-1]
2313 output['fileList'].append(filename)
2314 except Exception as e:
2315 print("Unable to collect dump: {dumpInfo}".format(dumpInfo=dump))
2316 errorInfo += "Exception collecting a bmc dump {dumpInfo}\n {eInfo}\n".format(dumpInfo=dump, eInfo=e)
Justin Thalerb4256672020-04-07 19:38:26 -05002317 exc_type, exc_obj, exc_tb = sys.exc_info()
2318 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2319 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2320 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002321 output['errors'] = errorInfo
2322 return output
Justin Thalere412dc22018-01-12 16:28:24 -06002323
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002324def collectServiceData(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002325 """
2326 Collects all data needed for service from the BMC
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002327
Justin Thalere412dc22018-01-12 16:28:24 -06002328 @param host: string, the hostname or IP address of the bmc
2329 @param args: contains additional arguments used by the collectServiceData sub command
2330 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002331 @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 -06002332 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002333
Justin Thaler22b1bb52018-03-15 13:31:32 -05002334 global toolVersion
Justin Thaler666cf342019-01-23 14:44:27 -06002335 filelist = []
2336 errorInfo = ""
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002337
Justin Thaler666cf342019-01-23 14:44:27 -06002338 #get current number of bmc dumps and create a new bmc dump
2339 dumpInitdata = csdDumpInitiate(host, args, session)
Justin Thalerb4256672020-04-07 19:38:26 -05002340 if 'dumpFailure' in dumpInitdata:
2341 return 'Collect service data is stopping due to not being able to create a new dump. No service data was collected.'
Justin Thaler666cf342019-01-23 14:44:27 -06002342 dumpcount = dumpInitdata['dumpcount']
2343 errorInfo += dumpInitdata['errors']
2344 #create the directory to put files
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002345 try:
2346 args.silent = True
Justin Thalercf1deae2018-05-25 19:35:21 -05002347 myDir = tempfile.gettempdir()+os.sep + host + "--" + datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%S")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002348 os.makedirs(myDir)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002349
Justin Thaler666cf342019-01-23 14:44:27 -06002350 except Exception as e:
2351 print('Unable to create the temporary directory for data collection. Ensure sufficient privileges to create temporary directory. Aborting.')
Justin Thalerb4256672020-04-07 19:38:26 -05002352 exc_type, exc_obj, exc_tb = sys.exc_info()
2353 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
2354 errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
2355 errorInfo += traceback.format_exc()
Justin Thaler666cf342019-01-23 14:44:27 -06002356 return("Python exception: {eInfo}".format(eInfo = e))
2357
2358 #Collect Inventory
2359 inventoryData = csdInventory(host, args, session, myDir)
2360 if 'fileLoc' in inventoryData:
2361 filelist.append(inventoryData['fileLoc'])
2362 errorInfo += inventoryData['errors']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002363 #Read all the sensor and OCC status
Justin Thaler666cf342019-01-23 14:44:27 -06002364 sensorData = csdSensors(host,args,session,myDir)
2365 if 'fileLoc' in sensorData:
2366 filelist.append(sensorData['fileLoc'])
2367 errorInfo += sensorData['errors']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002368 #Collect all of the LEDs status
Justin Thaler666cf342019-01-23 14:44:27 -06002369 ledStatus = csdLEDs(host, args, session, myDir)
2370 if 'fileLoc' in ledStatus:
2371 filelist.append(ledStatus['fileLoc'])
2372 errorInfo += ledStatus['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002373
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002374 #Collect the bmc logs
Justin Thaler666cf342019-01-23 14:44:27 -06002375 selShort = csdSelShortList(host, args, session, myDir)
2376 if 'fileLoc' in selShort:
2377 filelist.append(selShort['fileLoc'])
2378 errorInfo += selShort['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002379
Justin Thaler666cf342019-01-23 14:44:27 -06002380 parsedSELs = csdParsedSels(host, args, session, myDir)
2381 if 'fileLoc' in parsedSELs:
2382 filelist.append(parsedSELs['fileLoc'])
2383 errorInfo += parsedSELs['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002384
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002385 #collect RAW bmc enumeration
Justin Thaler666cf342019-01-23 14:44:27 -06002386 bmcRaw = csdFullEnumeration(host, args, session, myDir)
2387 if 'fileLoc' in bmcRaw:
2388 filelist.append(bmcRaw['fileLoc'])
2389 errorInfo += bmcRaw['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002390
Justin Thaler666cf342019-01-23 14:44:27 -06002391 #wait for new dump to finish being created
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002392 waitingForNewDump = True
2393 count = 0;
Justin Thalerb4256672020-04-07 19:38:26 -05002394 print("Waiting for new BMC dump to finish being created. Wait time could be up to 5 minutes")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002395 while(waitingForNewDump):
Justin Thaler666cf342019-01-23 14:44:27 -06002396 dumpList = bmcDumpList(host, args, session)['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002397 if len(dumpList) > dumpcount:
2398 waitingForNewDump = False
2399 break;
Justin Thalerb4256672020-04-07 19:38:26 -05002400 elif(count>150):
2401 print("Timed out waiting for bmc to make a new dump file. Continuing without it.")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002402 break;
2403 else:
2404 time.sleep(2)
2405 count += 1
Justin Thaler666cf342019-01-23 14:44:27 -06002406
2407 #collect all of the dump files
2408 getBMCDumps = csdCollectAllDumps(host, args, session, myDir)
2409 if 'fileList' in getBMCDumps:
2410 filelist+= getBMCDumps['fileList']
2411 errorInfo += getBMCDumps['errors']
2412
2413 #write the runtime errors to a file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002414 try:
Justin Thaler666cf342019-01-23 14:44:27 -06002415 with open(myDir +os.sep+'openbmctoolRuntimeErrors.txt', 'w') as f:
2416 f.write(errorInfo)
2417 print("OpenBMC tool runtime errors collected and stored in " + myDir + os.sep+ "openbmctoolRuntimeErrors.txt")
2418 filelist.append(myDir+os.sep+'openbmctoolRuntimeErrors.txt')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002419 except Exception as e:
Justin Thaler666cf342019-01-23 14:44:27 -06002420 print("Failed to write OpenBMC tool runtime errors to file system.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002421
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002422 #create the zip file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002423 try:
Justin Thalercf1deae2018-05-25 19:35:21 -05002424 filename = myDir.split(tempfile.gettempdir()+os.sep)[-1] + "_" + toolVersion + '_openbmc.zip'
Justin Thaler666cf342019-01-23 14:44:27 -06002425 zf = zipfile.ZipFile(myDir+os.sep + filename, 'w')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002426 for myfile in filelist:
2427 zf.write(myfile, os.path.basename(myfile))
2428 zf.close()
Justin Thaler666cf342019-01-23 14:44:27 -06002429 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 -06002430 except Exception as e:
2431 print("Failed to create zip file with collected information")
Justin Thaler666cf342019-01-23 14:44:27 -06002432 return "data collection finished"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002433
Justin Thalere412dc22018-01-12 16:28:24 -06002434
2435def healthCheck(host, args, session):
2436 """
2437 runs a health check on the platform
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002438
Justin Thalere412dc22018-01-12 16:28:24 -06002439 @param host: string, the hostname or IP address of the bmc
2440 @param args: contains additional arguments used by the bmc sub command
2441 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002442 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2443 """
Justin Thalere412dc22018-01-12 16:28:24 -06002444 #check fru status and get as json to easily work through
2445 d = vars(args)
2446 useJson = d['json']
2447 d['json'] = True
2448 d['verbose']= False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002449
Justin Thalere412dc22018-01-12 16:28:24 -06002450 frus = json.loads(fruStatus(host, args, session))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002451
Justin Thalere412dc22018-01-12 16:28:24 -06002452 hwStatus= "OK"
2453 performanceStatus = "OK"
2454 for key in frus:
2455 if frus[key]["Functional"] == "No" and frus[key]["Present"] == "Yes":
2456 hwStatus= "Degraded"
Justin Thalerfb9c81c2018-07-16 11:14:37 -05002457 if("power_supply" in key or "powersupply" in key):
2458 gpuCount =0
2459 for comp in frus:
Justin Thalere412dc22018-01-12 16:28:24 -06002460 if "gv100card" in comp:
2461 gpuCount +=1
2462 if gpuCount > 4:
2463 hwStatus = "Critical"
2464 performanceStatus="Degraded"
2465 break;
2466 elif("fan" in key):
2467 hwStatus = "Degraded"
2468 else:
2469 performanceStatus = "Degraded"
2470 if useJson:
2471 output = {"Hardware Status": hwStatus, "Performance": performanceStatus}
2472 output = json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
2473 else:
2474 output = ("Hardware Status: " + hwStatus +
2475 "\nPerformance: " +performanceStatus )
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002476
2477
Justin Thalere412dc22018-01-12 16:28:24 -06002478 #SW407886: Clear the duplicate entries
2479 #collect the dups
2480 d['devdebug'] = False
2481 sels = json.loads(selPrint(host, args, session))
2482 logNums2Clr = []
2483 oldestLogNum={"logNum": "bogus" ,"key" : ""}
2484 count = 0
2485 if sels['numAlerts'] > 0:
2486 for key in sels:
2487 if "numAlerts" in key:
2488 continue
2489 try:
2490 if "slave@00:00/00:00:00:06/sbefifo1-dev0/occ1-dev0" in sels[key]['Message']:
2491 count += 1
2492 if count > 1:
2493 #preserve first occurrence
2494 if sels[key]['timestamp'] < sels[oldestLogNum['key']]['timestamp']:
2495 oldestLogNum['key']=key
2496 oldestLogNum['logNum'] = sels[key]['logNum']
2497 else:
2498 oldestLogNum['key']=key
2499 oldestLogNum['logNum'] = sels[key]['logNum']
2500 logNums2Clr.append(sels[key]['logNum'])
2501 except KeyError:
2502 continue
2503 if(count >0):
2504 logNums2Clr.remove(oldestLogNum['logNum'])
2505 #delete the dups
2506 if count >1:
Justin Thalere412dc22018-01-12 16:28:24 -06002507 data = "{\"data\": [] }"
2508 for logNum in logNums2Clr:
2509 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
2510 try:
Justin Thaler27197622019-01-23 14:42:11 -06002511 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002512 except(requests.exceptions.Timeout):
2513 deleteFailed = True
2514 except(requests.exceptions.ConnectionError) as err:
2515 deleteFailed = True
2516 #End of defect resolve code
2517 d['json'] = useJson
2518 return output
2519
2520
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002521
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002522def bmc(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002523 """
2524 handles various bmc level commands, currently bmc rebooting
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002525
Justin Thalere412dc22018-01-12 16:28:24 -06002526 @param host: string, the hostname or IP address of the bmc
2527 @param args: contains additional arguments used by the bmc sub command
2528 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002529 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2530 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002531 if(args.type is not None):
2532 return bmcReset(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06002533 if(args.info):
2534 return "Not implemented at this time"
2535
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002536
Justin Thalere412dc22018-01-12 16:28:24 -06002537
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002538def bmcReset(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002539 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002540 controls resetting the bmc. warm reset reboots the bmc, cold reset removes the configuration and reboots.
2541
Justin Thalere412dc22018-01-12 16:28:24 -06002542 @param host: string, the hostname or IP address of the bmc
2543 @param args: contains additional arguments used by the bmcReset sub command
2544 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002545 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2546 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002547 if checkFWactivation(host, args, session):
2548 return ("BMC reset control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002549 if(args.type == "warm"):
2550 print("\nAttempting to reboot the BMC...:")
2551 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06002552 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06002553 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002554 return res.text
2555 elif(args.type =="cold"):
Justin Thalere412dc22018-01-12 16:28:24 -06002556 print("\nAttempting to reboot the BMC...:")
2557 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06002558 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06002559 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002560 return res.text
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002561 else:
2562 return "invalid command"
Justin Thalere412dc22018-01-12 16:28:24 -06002563
2564def gardClear(host, args, session):
2565 """
2566 clears the gard records from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002567
Justin Thalere412dc22018-01-12 16:28:24 -06002568 @param host: string, the hostname or IP address of the bmc
2569 @param args: contains additional arguments used by the gardClear sub command
2570 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002571 """
Justin Thalere412dc22018-01-12 16:28:24 -06002572 url="https://"+host+"/org/open_power/control/gard/action/Reset"
Justin Thalere412dc22018-01-12 16:28:24 -06002573 data = '{"data":[]}'
2574 try:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002575
Justin Thaler27197622019-01-23 14:42:11 -06002576 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002577 if res.status_code == 404:
2578 return "Command not supported by this firmware version"
2579 else:
2580 return res.text
2581 except(requests.exceptions.Timeout):
2582 return connectionErrHandler(args.json, "Timeout", None)
2583 except(requests.exceptions.ConnectionError) as err:
2584 return connectionErrHandler(args.json, "ConnectionError", err)
2585
2586def activateFWImage(host, args, session):
2587 """
2588 activates a firmware image on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002589
Justin Thalere412dc22018-01-12 16:28:24 -06002590 @param host: string, the hostname or IP address of the bmc
2591 @param args: contains additional arguments used by the fwflash sub command
2592 @param session: the active session to use
2593 @param fwID: the unique ID of the fw image to activate
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002594 """
Justin Thalere412dc22018-01-12 16:28:24 -06002595 fwID = args.imageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002596
Justin Thalere412dc22018-01-12 16:28:24 -06002597 #determine the existing versions
Justin Thalere412dc22018-01-12 16:28:24 -06002598 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2599 try:
Justin Thaler27197622019-01-23 14:42:11 -06002600 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002601 except(requests.exceptions.Timeout):
2602 return connectionErrHandler(args.json, "Timeout", None)
2603 except(requests.exceptions.ConnectionError) as err:
2604 return connectionErrHandler(args.json, "ConnectionError", err)
2605 existingSoftware = json.loads(resp.text)['data']
2606 altVersionID = ''
2607 versionType = ''
2608 imageKey = '/xyz/openbmc_project/software/'+fwID
2609 if imageKey in existingSoftware:
2610 versionType = existingSoftware[imageKey]['Purpose']
2611 for key in existingSoftware:
2612 if imageKey == key:
2613 continue
2614 if 'Purpose' in existingSoftware[key]:
2615 if versionType == existingSoftware[key]['Purpose']:
2616 altVersionID = key.split('/')[-1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002617
2618
2619
2620
Justin Thalere412dc22018-01-12 16:28:24 -06002621 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/attr/Priority"
2622 url1="https://"+host+"/xyz/openbmc_project/software/"+ altVersionID + "/attr/Priority"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002623 data = "{\"data\": 0}"
Justin Thalere412dc22018-01-12 16:28:24 -06002624 data1 = "{\"data\": 1 }"
2625 try:
Justin Thaler27197622019-01-23 14:42:11 -06002626 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
2627 resp1 = session.put(url1, headers=jsonHeader, data=data1, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002628 except(requests.exceptions.Timeout):
2629 return connectionErrHandler(args.json, "Timeout", None)
2630 except(requests.exceptions.ConnectionError) as err:
2631 return connectionErrHandler(args.json, "ConnectionError", err)
2632 if(not args.json):
2633 if resp.status_code == 200 and resp1.status_code == 200:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002634 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 -06002635 else:
2636 return "Firmware activation failed."
2637 else:
2638 return resp.text + resp1.text
Justin Thaler22b1bb52018-03-15 13:31:32 -05002639
2640def activateStatus(host, args, session):
2641 if checkFWactivation(host, args, session):
2642 return("Firmware is currently being activated. Do not reboot the BMC or start the Host OS")
2643 else:
2644 return("No firmware activations are pending")
2645
2646def extractFWimage(path, imageType):
2647 """
2648 extracts the bmc image and returns information about the package
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002649
Justin Thaler22b1bb52018-03-15 13:31:32 -05002650 @param path: the path and file name of the firmware image
2651 @param imageType: The type of image the user is trying to flash. Host or BMC
2652 @return: the image id associated with the package. returns an empty string on error.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002653 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002654 f = tempfile.TemporaryFile()
2655 tmpDir = tempfile.gettempdir()
2656 newImageID = ""
2657 if os.path.exists(path):
2658 try:
2659 imageFile = tarfile.open(path,'r')
2660 contents = imageFile.getmembers()
2661 for tf in contents:
2662 if 'MANIFEST' in tf.name:
2663 imageFile.extract(tf.name, path=tmpDir)
2664 with open(tempfile.gettempdir() +os.sep+ tf.name, 'r') as imageInfo:
2665 for line in imageInfo:
2666 if 'purpose' in line:
2667 purpose = line.split('=')[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002668 if imageType not in purpose.split('.')[-1]:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002669 print('The specified image is not for ' + imageType)
2670 print('Please try again with the image for ' + imageType)
2671 return ""
2672 if 'version' == line.split('=')[0]:
2673 version = line.split('=')[1].strip().encode('utf-8')
2674 m = hashlib.sha512()
2675 m.update(version)
2676 newImageID = m.hexdigest()[:8]
2677 break
2678 try:
2679 os.remove(tempfile.gettempdir() +os.sep+ tf.name)
2680 except OSError:
2681 pass
2682 return newImageID
2683 except tarfile.ExtractError as e:
2684 print('Unable to extract information from the firmware file.')
2685 print('Ensure you have write access to the directory: ' + tmpDir)
2686 return newImageID
2687 except tarfile.TarError as e:
2688 print('This is not a valid firmware file.')
2689 return newImageID
2690 print("This is not a valid firmware file.")
2691 return newImageID
2692 else:
2693 print('The filename and path provided are not valid.')
2694 return newImageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002695
Justin Thaler22b1bb52018-03-15 13:31:32 -05002696def getAllFWImageIDs(fwInvDict):
2697 """
2698 gets a list of all the firmware image IDs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002699
Justin Thaler22b1bb52018-03-15 13:31:32 -05002700 @param fwInvDict: the dictionary to search for FW image IDs
2701 @return: list containing string representation of the found image ids
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002702 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002703 idList = []
2704 for key in fwInvDict:
2705 if 'Version' in fwInvDict[key]:
2706 idList.append(key.split('/')[-1])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002707 return idList
2708
Justin Thalere412dc22018-01-12 16:28:24 -06002709def fwFlash(host, args, session):
2710 """
2711 updates the bmc firmware and pnor firmware
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002712
Justin Thalere412dc22018-01-12 16:28:24 -06002713 @param host: string, the hostname or IP address of the bmc
2714 @param args: contains additional arguments used by the fwflash sub command
2715 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002716 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002717 d = vars(args)
Justin Thalere412dc22018-01-12 16:28:24 -06002718 if(args.type == 'bmc'):
2719 purp = 'BMC'
2720 else:
2721 purp = 'Host'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002722
2723 #check power state of the machine. No concurrent FW updates allowed
Justin Thaler22b1bb52018-03-15 13:31:32 -05002724 d['powcmd'] = 'status'
2725 powerstate = chassisPower(host, args, session)
2726 if 'Chassis Power State: On' in powerstate:
2727 return("Aborting firmware update. Host is powered on. Please turn off the host and try again.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002728
Justin Thaler22b1bb52018-03-15 13:31:32 -05002729 #determine the existing images on the bmc
Justin Thalere412dc22018-01-12 16:28:24 -06002730 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2731 try:
Justin Thaler27197622019-01-23 14:42:11 -06002732 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002733 except(requests.exceptions.Timeout):
2734 return connectionErrHandler(args.json, "Timeout", None)
2735 except(requests.exceptions.ConnectionError) as err:
2736 return connectionErrHandler(args.json, "ConnectionError", err)
2737 oldsoftware = json.loads(resp.text)['data']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002738
Justin Thaler22b1bb52018-03-15 13:31:32 -05002739 #Extract the tar and get information from the manifest file
2740 newversionID = extractFWimage(args.fileloc, purp)
2741 if newversionID == "":
2742 return "Unable to verify FW image."
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002743
2744
Justin Thaler22b1bb52018-03-15 13:31:32 -05002745 #check if the new image is already on the bmc
2746 if newversionID not in getAllFWImageIDs(oldsoftware):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002747
Justin Thaler22b1bb52018-03-15 13:31:32 -05002748 #upload the file
2749 httpHeader = {'Content-Type':'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002750 httpHeader.update(xAuthHeader)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002751 url="https://"+host+"/upload/image"
2752 data=open(args.fileloc,'rb').read()
2753 print("Uploading file to BMC")
Justin Thalere412dc22018-01-12 16:28:24 -06002754 try:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002755 resp = session.post(url, headers=httpHeader, data=data, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -06002756 except(requests.exceptions.Timeout):
2757 return connectionErrHandler(args.json, "Timeout", None)
2758 except(requests.exceptions.ConnectionError) as err:
2759 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002760 if resp.status_code != 200:
2761 return "Failed to upload the file to the bmc"
Justin Thalere412dc22018-01-12 16:28:24 -06002762 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002763 print("Upload complete.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002764
Justin Thaler22b1bb52018-03-15 13:31:32 -05002765 #verify bmc processed the image
2766 software ={}
2767 for i in range(0, 5):
Justin Thaler22b1bb52018-03-15 13:31:32 -05002768 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2769 try:
Justin Thaler27197622019-01-23 14:42:11 -06002770 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002771 except(requests.exceptions.Timeout):
2772 return connectionErrHandler(args.json, "Timeout", None)
2773 except(requests.exceptions.ConnectionError) as err:
2774 return connectionErrHandler(args.json, "ConnectionError", err)
2775 software = json.loads(resp.text)['data']
2776 #check if bmc is done processing the new image
2777 if (newversionID in getAllFWImageIDs(software)):
Justin Thalere412dc22018-01-12 16:28:24 -06002778 break
Justin Thaler22b1bb52018-03-15 13:31:32 -05002779 else:
2780 time.sleep(15)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002781
Justin Thaler22b1bb52018-03-15 13:31:32 -05002782 #activate the new image
2783 print("Activating new image: "+newversionID)
2784 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID + "/attr/RequestedActivation"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002785 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05002786 try:
Justin Thaler27197622019-01-23 14:42:11 -06002787 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002788 except(requests.exceptions.Timeout):
2789 return connectionErrHandler(args.json, "Timeout", None)
2790 except(requests.exceptions.ConnectionError) as err:
2791 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002792
Justin Thaler22b1bb52018-03-15 13:31:32 -05002793 #wait for the activation to complete, timeout after ~1 hour
2794 i=0
2795 while i < 360:
2796 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002797 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05002798 try:
Justin Thaler27197622019-01-23 14:42:11 -06002799 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002800 except(requests.exceptions.Timeout):
2801 return connectionErrHandler(args.json, "Timeout", None)
2802 except(requests.exceptions.ConnectionError) as err:
2803 return connectionErrHandler(args.json, "ConnectionError", err)
2804 fwInfo = json.loads(resp.text)['data']
2805 if 'Activating' not in fwInfo['Activation'] and 'Activating' not in fwInfo['RequestedActivation']:
2806 print('')
2807 break
2808 else:
2809 sys.stdout.write('.')
2810 sys.stdout.flush()
2811 time.sleep(10) #check every 10 seconds
2812 return "Firmware flash and activation completed. Please reboot the bmc and then boot the host OS for the changes to take effect. "
2813 else:
2814 print("This image has been found on the bmc. Activating image: " + newversionID)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002815
Justin Thaler22b1bb52018-03-15 13:31:32 -05002816 d['imageID'] = newversionID
2817 return activateFWImage(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06002818
Justin Thaler3d71d402018-07-24 14:35:39 -05002819def getFWInventoryAttributes(rawFWInvItem, ID):
2820 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002821 gets and lists all of the firmware in the system.
2822
Justin Thaler3d71d402018-07-24 14:35:39 -05002823 @return: returns a dictionary containing the image attributes
2824 """
2825 reqActivation = rawFWInvItem["RequestedActivation"].split('.')[-1]
2826 pendingActivation = ""
2827 if reqActivation == "None":
2828 pendingActivation = "No"
2829 else:
2830 pendingActivation = "Yes"
2831 firmwareAttr = {ID: {
2832 "Purpose": rawFWInvItem["Purpose"].split('.')[-1],
2833 "Version": rawFWInvItem["Version"],
2834 "RequestedActivation": pendingActivation,
2835 "ID": ID}}
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002836
Justin Thaler3d71d402018-07-24 14:35:39 -05002837 if "ExtendedVersion" in rawFWInvItem:
2838 firmwareAttr[ID]['ExtendedVersion'] = rawFWInvItem['ExtendedVersion'].split(',')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002839 else:
Justin Thaler3d71d402018-07-24 14:35:39 -05002840 firmwareAttr[ID]['ExtendedVersion'] = ""
2841 return firmwareAttr
2842
2843def parseFWdata(firmwareDict):
2844 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002845 creates a dictionary with parsed firmware data
2846
Justin Thaler3d71d402018-07-24 14:35:39 -05002847 @return: returns a dictionary containing the image attributes
2848 """
2849 firmwareInfoDict = {"Functional": {}, "Activated":{}, "NeedsActivated":{}}
2850 for key in firmwareDict['data']:
2851 #check for valid endpoint
2852 if "Purpose" in firmwareDict['data'][key]:
2853 id = key.split('/')[-1]
2854 if firmwareDict['data'][key]['Activation'].split('.')[-1] == "Active":
2855 fwActivated = True
2856 else:
2857 fwActivated = False
Justin Thalercb68e062019-03-26 19:04:52 -05002858 if 'Priority' in firmwareDict['data'][key]:
2859 if firmwareDict['data'][key]['Priority'] == 0:
2860 firmwareInfoDict['Functional'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2861 elif firmwareDict['data'][key]['Priority'] >= 0 and fwActivated:
2862 firmwareInfoDict['Activated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2863 else:
2864 firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
Justin Thaler3d71d402018-07-24 14:35:39 -05002865 else:
Justin Thalercb68e062019-03-26 19:04:52 -05002866 firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
Justin Thaler3d71d402018-07-24 14:35:39 -05002867 emptySections = []
2868 for key in firmwareInfoDict:
2869 if len(firmwareInfoDict[key])<=0:
2870 emptySections.append(key)
2871 for key in emptySections:
2872 del firmwareInfoDict[key]
2873 return firmwareInfoDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002874
Justin Thaler3d71d402018-07-24 14:35:39 -05002875def displayFWInvenory(firmwareInfoDict, args):
2876 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002877 gets and lists all of the firmware in the system.
2878
Justin Thaler3d71d402018-07-24 14:35:39 -05002879 @return: returns a string containing all of the firmware information
2880 """
2881 output = ""
2882 if not args.json:
2883 for key in firmwareInfoDict:
2884 for subkey in firmwareInfoDict[key]:
2885 firmwareInfoDict[key][subkey]['ExtendedVersion'] = str(firmwareInfoDict[key][subkey]['ExtendedVersion'])
2886 if not args.verbose:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002887 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002888 colNames = ["Purpose", "Version", "ID"]
2889 keylist = ["Purpose", "Version", "ID"]
2890 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2891 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002892 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002893 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2894 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002895 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002896 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002897
Justin Thaler3d71d402018-07-24 14:35:39 -05002898 else:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002899 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002900 colNames = ["Purpose", "Version", "ID", "Pending Activation", "Extended Version"]
2901 keylist = ["Purpose", "Version", "ID", "RequestedActivation", "ExtendedVersion"]
2902 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2903 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002904 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002905 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2906 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002907 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002908 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
2909 return output
2910 else:
2911 return str(json.dumps(firmwareInfoDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
2912
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002913def firmwareList(host, args, session):
Justin Thaler3d71d402018-07-24 14:35:39 -05002914 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002915 gets and lists all of the firmware in the system.
2916
Justin Thaler3d71d402018-07-24 14:35:39 -05002917 @return: returns a string containing all of the firmware information
2918 """
Justin Thaler3d71d402018-07-24 14:35:39 -05002919 url="https://{hostname}/xyz/openbmc_project/software/enumerate".format(hostname=host)
2920 try:
Justin Thaler27197622019-01-23 14:42:11 -06002921 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3d71d402018-07-24 14:35:39 -05002922 except(requests.exceptions.Timeout):
2923 return(connectionErrHandler(args.json, "Timeout", None))
2924 firmwareDict = json.loads(res.text)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002925
Justin Thaler3d71d402018-07-24 14:35:39 -05002926 #sort the received information
2927 firmwareInfoDict = parseFWdata(firmwareDict)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002928
Justin Thaler3d71d402018-07-24 14:35:39 -05002929 #display the information
2930 return displayFWInvenory(firmwareInfoDict, args)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002931
2932
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002933def deleteFWVersion(host, args, session):
2934 """
2935 deletes a firmware version on the BMC
2936
2937 @param host: string, the hostname or IP address of the BMC
2938 @param args: contains additional arguments used by the fwflash sub command
2939 @param session: the active session to use
2940 @param fwID: the unique ID of the fw version to delete
2941 """
2942 fwID = args.versionID
2943
2944 print("Deleting version: "+fwID)
2945 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/action/Delete"
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002946 data = "{\"data\": [] }"
2947
2948 try:
Justin Thaler27197622019-01-23 14:42:11 -06002949 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002950 except(requests.exceptions.Timeout):
2951 return(connectionErrHandler(args.json, "Timeout", None))
2952 if res.status_code == 200:
2953 return ('The firmware version has been deleted')
2954 else:
2955 return ('Unable to delete the specified firmware version')
2956
2957
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002958def restLogging(host, args, session):
2959 """
2960 Called by the logging function. Turns REST API logging on/off.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002961
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002962 @param host: string, the hostname or IP address of the bmc
2963 @param args: contains additional arguments used by the logging sub command
2964 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002965 @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 -05002966 """
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002967 url="https://"+host+"/xyz/openbmc_project/logging/rest_api_logs/attr/Enabled"
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002968
2969 if(args.rest_logging == 'on'):
2970 data = '{"data": 1}'
2971 elif(args.rest_logging == 'off'):
2972 data = '{"data": 0}'
2973 else:
2974 return "Invalid logging rest_api command"
2975
2976 try:
Justin Thaler27197622019-01-23 14:42:11 -06002977 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002978 except(requests.exceptions.Timeout):
2979 return(connectionErrHandler(args.json, "Timeout", None))
2980 return res.text
2981
2982
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002983def remoteLogging(host, args, session):
2984 """
2985 Called by the logging function. View config information for/disable remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002986
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002987 @param host: string, the hostname or IP address of the bmc
2988 @param args: contains additional arguments used by the logging sub command
2989 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002990 @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 -05002991 """
2992
2993 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002994
2995 try:
2996 if(args.remote_logging == 'view'):
Justin Thaler27197622019-01-23 14:42:11 -06002997 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002998 elif(args.remote_logging == 'disable'):
Justin Thaler27197622019-01-23 14:42:11 -06002999 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": 0}, verify=False, timeout=baseTimeout)
3000 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": ""}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003001 else:
3002 return "Invalid logging remote_logging command"
3003 except(requests.exceptions.Timeout):
3004 return(connectionErrHandler(args.json, "Timeout", None))
3005 return res.text
3006
3007
3008def remoteLoggingConfig(host, args, session):
3009 """
3010 Called by the logging function. Configures remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003011
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003012 @param host: string, the hostname or IP address of the bmc
3013 @param args: contains additional arguments used by the logging sub command
3014 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06003015 @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 -05003016 """
3017
3018 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003019
3020 try:
Justin Thaler27197622019-01-23 14:42:11 -06003021 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": args.port}, verify=False, timeout=baseTimeout)
3022 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": args.address}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003023 except(requests.exceptions.Timeout):
3024 return(connectionErrHandler(args.json, "Timeout", None))
3025 return res.text
3026
Marri Devender Rao82590dc2019-06-06 04:54:22 -05003027def redfishSupportPresent(host, session):
3028 url = "https://" + host + "/redfish/v1"
3029 try:
3030 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
3031 except(requests.exceptions.Timeout):
3032 return False
3033 except(requests.exceptions.ConnectionError) as err:
3034 return False
3035 if resp.status_code != 200:
3036 return False
3037 else:
3038 return True
Ratan Gupta9166cd22018-10-01 18:09:40 +05303039
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003040def certificateUpdate(host, args, session):
3041 """
3042 Called by certificate management function. update server/client/authority certificates
3043 Example:
3044 certificate update server https -f cert.pem
3045 certificate update authority ldap -f Root-CA.pem
3046 certificate update client ldap -f cert.pem
3047 @param host: string, the hostname or IP address of the bmc
3048 @param args: contains additional arguments used by the certificate update sub command
3049 @param session: the active session to use
3050 """
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003051 httpHeader = {'Content-Type': 'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06003052 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003053 data = open(args.fileloc, 'rb').read()
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003054 try:
Marri Devender Rao82590dc2019-06-06 04:54:22 -05003055 if redfishSupportPresent(host, session):
Marri Devender Rao62db08a2019-08-22 03:16:02 -05003056 if(args.type.lower() == 'server' and args.service.lower() != "https"):
3057 return "Invalid service type"
3058 if(args.type.lower() == 'client' and args.service.lower() != "ldap"):
3059 return "Invalid service type"
3060 if(args.type.lower() == 'authority' and args.service.lower() != "ldap"):
3061 return "Invalid service type"
Marri Devender Rao82590dc2019-06-06 04:54:22 -05003062 url = "";
3063 if(args.type.lower() == 'server'):
3064 url = "https://" + host + \
3065 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"
3066 elif(args.type.lower() == 'client'):
3067 url = "https://" + host + \
3068 "/redfish/v1/AccountService/LDAP/Certificates"
3069 elif(args.type.lower() == 'authority'):
3070 url = "https://" + host + \
3071 "/redfish/v1/Managers/bmc/Truststore/Certificates"
3072 else:
3073 return "Unsupported certificate type"
3074 resp = session.post(url, headers=httpHeader, data=data,
3075 verify=False)
3076 else:
3077 url = "https://" + host + "/xyz/openbmc_project/certs/" + \
3078 args.type.lower() + "/" + args.service.lower()
3079 resp = session.put(url, headers=httpHeader, data=data, verify=False)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003080 except(requests.exceptions.Timeout):
3081 return(connectionErrHandler(args.json, "Timeout", None))
3082 except(requests.exceptions.ConnectionError) as err:
3083 return connectionErrHandler(args.json, "ConnectionError", err)
3084 if resp.status_code != 200:
3085 print(resp.text)
3086 return "Failed to update the certificate"
3087 else:
Marri Devender Rao82590dc2019-06-06 04:54:22 -05003088 print("Update complete.")
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003089
3090def certificateDelete(host, args, session):
3091 """
3092 Called by certificate management function to delete certificate
3093 Example:
3094 certificate delete server https
3095 certificate delete authority ldap
3096 certificate delete client ldap
3097 @param host: string, the hostname or IP address of the bmc
3098 @param args: contains additional arguments used by the certificate delete sub command
3099 @param session: the active session to use
3100 """
Marri Devender Rao77e78682019-07-17 03:18:35 -05003101 if redfishSupportPresent(host, session):
3102 return "Not supported, please use certificate replace instead";
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003103 httpHeader = {'Content-Type': 'multipart/form-data'}
Matt Spinler220c3c42019-01-04 15:09:29 -06003104 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05003105 url = "https://" + host + "/xyz/openbmc_project/certs/" + args.type.lower() + "/" + args.service.lower()
3106 print("Deleting certificate url=" + url)
3107 try:
3108 resp = session.delete(url, headers=httpHeader)
3109 except(requests.exceptions.Timeout):
3110 return(connectionErrHandler(args.json, "Timeout", None))
3111 except(requests.exceptions.ConnectionError) as err:
3112 return connectionErrHandler(args.json, "ConnectionError", err)
3113 if resp.status_code != 200:
3114 print(resp.text)
3115 return "Failed to delete the certificate"
3116 else:
Marri Devender Rao77e78682019-07-17 03:18:35 -05003117 print("Delete complete.")
Deepak Kodihalli02d53282018-09-18 06:53:31 -05003118
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05003119def certificateReplace(host, args, session):
3120 """
3121 Called by certificate management function. replace server/client/
3122 authority certificates
3123 Example:
3124 certificate replace server https -f cert.pem
3125 certificate replace authority ldap -f Root-CA.pem
3126 certificate replace client ldap -f cert.pem
3127 @param host: string, the hostname or IP address of the bmc
3128 @param args: contains additional arguments used by the certificate
3129 replace sub command
3130 @param session: the active session to use
3131 """
3132 cert = open(args.fileloc, 'rb').read()
3133 try:
3134 if redfishSupportPresent(host, session):
3135 httpHeader = {'Content-Type': 'application/json'}
3136 httpHeader.update(xAuthHeader)
3137 url = "";
Marri Devender Rao62db08a2019-08-22 03:16:02 -05003138 if(args.type.lower() == 'server' and args.service.lower() != "https"):
3139 return "Invalid service type"
3140 if(args.type.lower() == 'client' and args.service.lower() != "ldap"):
3141 return "Invalid service type"
3142 if(args.type.lower() == 'authority' and args.service.lower() != "ldap"):
3143 return "Invalid service type"
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05003144 if(args.type.lower() == 'server'):
3145 url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
3146 elif(args.type.lower() == 'client'):
3147 url = "/redfish/v1/AccountService/LDAP/Certificates/1"
3148 elif(args.type.lower() == 'authority'):
3149 url = "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
3150 replaceUrl = "https://" + host + \
3151 "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"
3152 data ={"CertificateUri":{"@odata.id":url}, "CertificateType":"PEM",
3153 "CertificateString":cert}
3154 resp = session.post(replaceUrl, headers=httpHeader, json=data, verify=False)
3155 else:
3156 httpHeader = {'Content-Type': 'application/octet-stream'}
3157 httpHeader.update(xAuthHeader)
3158 url = "https://" + host + "/xyz/openbmc_project/certs/" + \
3159 args.type.lower() + "/" + args.service.lower()
3160 resp = session.delete(url, headers=httpHeader)
3161 resp = session.put(url, headers=httpHeader, data=cert, verify=False)
3162 except(requests.exceptions.Timeout):
3163 return(connectionErrHandler(args.json, "Timeout", None))
3164 except(requests.exceptions.ConnectionError) as err:
3165 return connectionErrHandler(args.json, "ConnectionError", err)
3166 if resp.status_code != 200:
3167 print(resp.text)
3168 return "Failed to replace the certificate"
3169 else:
3170 print("Replace complete.")
3171 return resp.text
3172
Marri Devender Rao34646402019-07-01 05:46:03 -05003173def certificateDisplay(host, args, session):
3174 """
3175 Called by certificate management function. display server/client/
3176 authority certificates
3177 Example:
3178 certificate display server
3179 certificate display authority
3180 certificate display client
3181 @param host: string, the hostname or IP address of the bmc
3182 @param args: contains additional arguments used by the certificate
3183 display sub command
3184 @param session: the active session to use
3185 """
3186 if not redfishSupportPresent(host, session):
3187 return "Not supported";
3188
3189 httpHeader = {'Content-Type': 'application/octet-stream'}
3190 httpHeader.update(xAuthHeader)
3191 if(args.type.lower() == 'server'):
3192 url = "https://" + host + \
3193 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
3194 elif(args.type.lower() == 'client'):
3195 url = "https://" + host + \
3196 "/redfish/v1/AccountService/LDAP/Certificates/1"
3197 elif(args.type.lower() == 'authority'):
3198 url = "https://" + host + \
3199 "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
3200 try:
3201 resp = session.get(url, headers=httpHeader, verify=False)
3202 except(requests.exceptions.Timeout):
3203 return(connectionErrHandler(args.json, "Timeout", None))
3204 except(requests.exceptions.ConnectionError) as err:
3205 return connectionErrHandler(args.json, "ConnectionError", err)
3206 if resp.status_code != 200:
3207 print(resp.text)
3208 return "Failed to display the certificate"
3209 else:
3210 print("Display complete.")
3211 return resp.text
3212
Marri Devender Raoa208ff82019-07-01 05:51:27 -05003213def certificateList(host, args, session):
3214 """
3215 Called by certificate management function.
3216 Example:
3217 certificate list
3218 @param host: string, the hostname or IP address of the bmc
3219 @param args: contains additional arguments used by the certificate
3220 list sub command
3221 @param session: the active session to use
3222 """
3223 if not redfishSupportPresent(host, session):
3224 return "Not supported";
3225
3226 httpHeader = {'Content-Type': 'application/octet-stream'}
3227 httpHeader.update(xAuthHeader)
3228 url = "https://" + host + \
3229 "/redfish/v1/CertificateService/CertificateLocations/"
3230 try:
3231 resp = session.get(url, headers=httpHeader, verify=False)
3232 except(requests.exceptions.Timeout):
3233 return(connectionErrHandler(args.json, "Timeout", None))
3234 except(requests.exceptions.ConnectionError) as err:
3235 return connectionErrHandler(args.json, "ConnectionError", err)
3236 if resp.status_code != 200:
3237 print(resp.text)
3238 return "Failed to list certificates"
3239 else:
3240 print("List certificates complete.")
3241 return resp.text
3242
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003243def certificateGenerateCSR(host, args, session):
3244 """
3245 Called by certificate management function. Generate CSR for server/
3246 client certificates
3247 Example:
Marri Devender Raodf0e1a42019-09-09 08:18:27 -05003248 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
3249 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 -05003250 @param host: string, the hostname or IP address of the bmc
3251 @param args: contains additional arguments used by the certificate replace sub command
3252 @param session: the active session to use
3253 """
3254 if not redfishSupportPresent(host, session):
3255 return "Not supported";
3256
3257 httpHeader = {'Content-Type': 'application/octet-stream'}
3258 httpHeader.update(xAuthHeader)
3259 url = "";
3260 if(args.type.lower() == 'server'):
3261 url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
Marri Devender Rao88064f02019-08-19 09:00:30 -05003262 usage_list = ["ServerAuthentication"]
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003263 elif(args.type.lower() == 'client'):
3264 url = "/redfish/v1/AccountService/LDAP/Certificates/"
Marri Devender Rao88064f02019-08-19 09:00:30 -05003265 usage_list = ["ClientAuthentication"]
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003266 elif(args.type.lower() == 'authority'):
3267 url = "/redfish/v1/Managers/bmc/Truststore/Certificates/"
3268 print("Generating CSR url=" + url)
3269 generateCSRUrl = "https://" + host + \
3270 "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"
3271 try:
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003272 alt_name_list = args.alternativeNames.split(",")
3273 data ={"CertificateCollection":{"@odata.id":url},
3274 "CommonName":args.commonName, "City":args.city,
3275 "Country":args.country, "Organization":args.organization,
3276 "OrganizationalUnit":args.organizationUnit, "State":args.state,
Marri Devender Raodf0e1a42019-09-09 08:18:27 -05003277 "KeyPairAlgorithm":args.keyPairAlgorithm, "KeyCurveId":args.keyCurveId,
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003278 "AlternativeNames":alt_name_list, "ContactPerson":args.contactPerson,
3279 "Email":args.email, "GivenName":args.givenname, "Initials":args.initials,
3280 "KeyUsage":usage_list, "Surname":args.surname,
3281 "UnstructuredName":args.unstructuredname}
3282 resp = session.post(generateCSRUrl, headers=httpHeader,
3283 json=data, verify=False)
3284 except(requests.exceptions.Timeout):
3285 return(connectionErrHandler(args.json, "Timeout", None))
3286 except(requests.exceptions.ConnectionError) as err:
3287 return connectionErrHandler(args.json, "ConnectionError", err)
3288 if resp.status_code != 200:
3289 print(resp.text)
3290 return "Failed to generate CSR"
3291 else:
3292 print("GenerateCSR complete.")
3293 return resp.text
3294
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003295def enableLDAPConfig(host, args, session):
Ratan Gupta9166cd22018-10-01 18:09:40 +05303296 """
3297 Called by the ldap function. Configures LDAP.
3298
3299 @param host: string, the hostname or IP address of the bmc
3300 @param args: contains additional arguments used by the ldap subcommand
3301 @param session: the active session to use
3302 @param args.json: boolean, if this flag is set to true, the output will
3303 be provided in json format for programmatic consumption
3304 """
3305
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003306 if(isRedfishSupport):
3307 return enableLDAP(host, args, session)
3308 else:
3309 return enableLegacyLDAP(host, args, session)
3310
3311def enableLegacyLDAP(host, args, session):
3312 """
3313 Called by the ldap function. Configures LDAP on Lagecy systems.
3314
3315 @param host: string, the hostname or IP address of the bmc
3316 @param args: contains additional arguments used by the ldap subcommand
3317 @param session: the active session to use
3318 @param args.json: boolean, if this flag is set to true, the output will
3319 be provided in json format for programmatic consumption
3320 """
3321
Ratan Gupta9166cd22018-10-01 18:09:40 +05303322 url='https://'+host+'/xyz/openbmc_project/user/ldap/action/CreateConfig'
Ratan Gupta9166cd22018-10-01 18:09:40 +05303323 scope = {
3324 'sub' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.sub',
3325 'one' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.one',
3326 'base': 'xyz.openbmc_project.User.Ldap.Create.SearchScope.base'
3327 }
3328
3329 serverType = {
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003330 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Create.Type.ActiveDirectory',
3331 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Create.Type.OpenLdap'
Ratan Gupta9166cd22018-10-01 18:09:40 +05303332 }
3333
3334 data = {"data": [args.uri, args.bindDN, args.baseDN, args.bindPassword, scope[args.scope], serverType[args.serverType]]}
3335
3336 try:
Justin Thaler27197622019-01-23 14:42:11 -06003337 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Ratan Gupta9166cd22018-10-01 18:09:40 +05303338 except(requests.exceptions.Timeout):
3339 return(connectionErrHandler(args.json, "Timeout", None))
3340 except(requests.exceptions.ConnectionError) as err:
3341 return connectionErrHandler(args.json, "ConnectionError", err)
3342
3343 return res.text
3344
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003345def enableLDAP(host, args, session):
3346 """
3347 Called by the ldap function. Configures LDAP for systems with latest user-manager design changes
3348
3349 @param host: string, the hostname or IP address of the bmc
3350 @param args: contains additional arguments used by the ldap subcommand
3351 @param session: the active session to use
3352 @param args.json: boolean, if this flag is set to true, the output will
3353 be provided in json format for programmatic consumption
3354 """
3355
3356 scope = {
3357 'sub' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.sub',
3358 'one' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.one',
3359 'base': 'xyz.openbmc_project.User.Ldap.Config.SearchScope.base'
3360 }
3361
3362 serverType = {
3363 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Config.Type.ActiveDirectory',
3364 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap'
3365 }
3366
3367 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
3368
3369 serverTypeEnabled = getLDAPTypeEnabled(host,session)
3370 serverTypeToBeEnabled = args.serverType
3371
3372 #If the given LDAP type is already enabled, then return
3373 if (serverTypeToBeEnabled == serverTypeEnabled):
3374 return("Server type " + serverTypeToBeEnabled + " is already enabled...")
3375
3376 try:
3377
3378 # Copy the role map from the currently enabled LDAP server type
3379 # to the newly enabled server type
3380 # Disable the currently enabled LDAP server type. Unless
3381 # it is disabled, we cannot enable a new LDAP server type
3382 if (serverTypeEnabled is not None):
3383
3384 if (serverTypeToBeEnabled != serverTypeEnabled):
3385 res = syncRoleMap(host,args,session,serverTypeEnabled,serverTypeToBeEnabled)
3386
3387 data = "{\"data\": 0 }"
3388 res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3389
3390 data = {"data": args.baseDN}
3391 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBaseDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3392 if (res.status_code != requests.codes.ok):
3393 print("Updates to the property LDAPBaseDN failed...")
3394 return(res.text)
3395
3396 data = {"data": args.bindDN}
3397 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3398 if (res.status_code != requests.codes.ok):
3399 print("Updates to the property LDAPBindDN failed...")
3400 return(res.text)
3401
3402 data = {"data": args.bindPassword}
3403 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDNPassword', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3404 if (res.status_code != requests.codes.ok):
3405 print("Updates to the property LDAPBindDNPassword failed...")
3406 return(res.text)
3407
3408 data = {"data": scope[args.scope]}
3409 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPSearchScope', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3410 if (res.status_code != requests.codes.ok):
3411 print("Updates to the property LDAPSearchScope failed...")
3412 return(res.text)
3413
3414 data = {"data": args.uri}
3415 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPServerURI', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3416 if (res.status_code != requests.codes.ok):
3417 print("Updates to the property LDAPServerURI failed...")
3418 return(res.text)
3419
3420 data = {"data": args.groupAttrName}
3421 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/GroupNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3422 if (res.status_code != requests.codes.ok):
3423 print("Updates to the property GroupNameAttribute failed...")
3424 return(res.text)
3425
3426 data = {"data": args.userAttrName}
3427 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/UserNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3428 if (res.status_code != requests.codes.ok):
3429 print("Updates to the property UserNameAttribute failed...")
3430 return(res.text)
3431
3432 #After updating the properties, enable the new server type
3433 data = "{\"data\": 1 }"
3434 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3435
3436 except(requests.exceptions.Timeout):
3437 return(connectionErrHandler(args.json, "Timeout", None))
3438 except(requests.exceptions.ConnectionError) as err:
3439 return connectionErrHandler(args.json, "ConnectionError", err)
3440 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05303441
3442def disableLDAP(host, args, session):
3443 """
3444 Called by the ldap function. Deletes the LDAP Configuration.
3445
3446 @param host: string, the hostname or IP address of the bmc
3447 @param args: contains additional arguments used by the ldap subcommand
3448 @param session: the active session to use
3449 @param args.json: boolean, if this flag is set to true, the output
3450 will be provided in json format for programmatic consumption
3451 """
3452
Ratan Gupta9166cd22018-10-01 18:09:40 +05303453 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003454 if (isRedfishSupport) :
3455
3456 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
3457
3458 serverTypeEnabled = getLDAPTypeEnabled(host,session)
3459
3460 if (serverTypeEnabled is not None):
3461 #To keep the role map in sync,
3462 #If the server type being disabled has role map, then
3463 # - copy the role map to the other server type(s)
3464 for serverType in serverTypeMap.keys():
3465 if (serverType != serverTypeEnabled):
3466 res = syncRoleMap(host,args,session,serverTypeEnabled,serverType)
3467
3468 #Disable the currently enabled LDAP server type
3469 data = "{\"data\": 0 }"
3470 res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3471
3472 else:
3473 return("LDAP server has not been enabled...")
3474
3475 else :
3476 url='https://'+host+'/xyz/openbmc_project/user/ldap/config/action/delete'
3477 data = {"data": []}
3478 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3479
Ratan Gupta9166cd22018-10-01 18:09:40 +05303480 except(requests.exceptions.Timeout):
3481 return(connectionErrHandler(args.json, "Timeout", None))
3482 except(requests.exceptions.ConnectionError) as err:
3483 return connectionErrHandler(args.json, "ConnectionError", err)
3484
3485 return res.text
3486
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003487def enableDHCP(host, args, session):
3488
3489 """
3490 Called by the network function. Enables DHCP.
3491
3492 @param host: string, the hostname or IP address of the bmc
3493 @param args: contains additional arguments used by the ldap subcommand
3494 args.json: boolean, if this flag is set to true, the output
3495 will be provided in json format for programmatic consumption
3496 @param session: the active session to use
3497 """
3498
3499 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3500 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003501 data = "{\"data\": 1 }"
3502 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003503 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003504 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003505
3506 except(requests.exceptions.Timeout):
3507 return(connectionErrHandler(args.json, "Timeout", None))
3508 except(requests.exceptions.ConnectionError) as err:
3509 return connectionErrHandler(args.json, "ConnectionError", err)
3510 if res.status_code == 403:
3511 return "The specified Interface"+"("+args.Interface+")"+\
3512 " doesn't exist"
3513
3514 return res.text
3515
3516
3517def disableDHCP(host, args, session):
3518 """
3519 Called by the network function. Disables DHCP.
3520
3521 @param host: string, the hostname or IP address of the bmc
3522 @param args: contains additional arguments used by the ldap subcommand
3523 args.json: boolean, if this flag is set to true, the output
3524 will be provided in json format for programmatic consumption
3525 @param session: the active session to use
3526 """
3527
3528 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3529 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003530 data = "{\"data\": 0 }"
3531 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003532 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003533 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003534 except(requests.exceptions.Timeout):
3535 return(connectionErrHandler(args.json, "Timeout", None))
3536 except(requests.exceptions.ConnectionError) as err:
3537 return connectionErrHandler(args.json, "ConnectionError", err)
3538 if res.status_code == 403:
3539 return "The specified Interface"+"("+args.Interface+")"+\
3540 " doesn't exist"
3541 return res.text
3542
3543
3544def getHostname(host, args, session):
3545
3546 """
3547 Called by the network function. Prints out the Hostname.
3548
3549 @param host: string, the hostname or IP address of the bmc
3550 @param args: contains additional arguments used by the ldap subcommand
3551 args.json: boolean, if this flag is set to true, the output
3552 will be provided in json format for programmatic consumption
3553 @param session: the active session to use
3554 """
3555
3556 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003557
3558 try:
Justin Thaler27197622019-01-23 14:42:11 -06003559 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003560 except(requests.exceptions.Timeout):
3561 return(connectionErrHandler(args.json, "Timeout", None))
3562 except(requests.exceptions.ConnectionError) as err:
3563 return connectionErrHandler(args.json, "ConnectionError", err)
3564
3565 return res.text
3566
3567
3568def setHostname(host, args, session):
3569 """
3570 Called by the network function. Sets the Hostname.
3571
3572 @param host: string, the hostname or IP address of the bmc
3573 @param args: contains additional arguments used by the ldap subcommand
3574 args.json: boolean, if this flag is set to true, the output
3575 will be provided in json format for programmatic consumption
3576 @param session: the active session to use
3577 """
3578
3579 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003580
3581 data = {"data": args.HostName}
3582
3583 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003584 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003585 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003586 except(requests.exceptions.Timeout):
3587 return(connectionErrHandler(args.json, "Timeout", None))
3588 except(requests.exceptions.ConnectionError) as err:
3589 return connectionErrHandler(args.json, "ConnectionError", err)
3590
3591 return res.text
3592
3593
3594def getDomainName(host, args, session):
3595
3596 """
3597 Called by the network function. Prints out the DomainName.
3598
3599 @param host: string, the hostname or IP address of the bmc
3600 @param args: contains additional arguments used by the ldap subcommand
3601 args.json: boolean, if this flag is set to true, the output
3602 will be provided in json format for programmatic consumption
3603 @param session: the active session to use
3604 """
3605
3606 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3607 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003608
3609 try:
Justin Thaler27197622019-01-23 14:42:11 -06003610 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003611 except(requests.exceptions.Timeout):
3612 return(connectionErrHandler(args.json, "Timeout", None))
3613 except(requests.exceptions.ConnectionError) as err:
3614 return connectionErrHandler(args.json, "ConnectionError", err)
3615 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003616 return "The DomainName is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003617
3618 return res.text
3619
3620
3621def setDomainName(host, args, session):
3622 """
3623 Called by the network function. Sets the DomainName.
3624
3625 @param host: string, the hostname or IP address of the bmc
3626 @param args: contains additional arguments used by the ldap subcommand
3627 args.json: boolean, if this flag is set to true, the output
3628 will be provided in json format for programmatic consumption
3629 @param session: the active session to use
3630 """
3631
3632 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3633 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003634
3635 data = {"data": args.DomainName.split(",")}
3636
3637 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003638 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003639 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003640 except(requests.exceptions.Timeout):
3641 return(connectionErrHandler(args.json, "Timeout", None))
3642 except(requests.exceptions.ConnectionError) as err:
3643 return connectionErrHandler(args.json, "ConnectionError", err)
3644 if res.status_code == 403:
3645 return "The specified Interface"+"("+args.Interface+")"+\
3646 " doesn't exist"
3647
3648 return res.text
3649
3650
3651def getMACAddress(host, args, session):
3652
3653 """
3654 Called by the network function. Prints out the MACAddress.
3655
3656 @param host: string, the hostname or IP address of the bmc
3657 @param args: contains additional arguments used by the ldap subcommand
3658 args.json: boolean, if this flag is set to true, the output
3659 will be provided in json format for programmatic consumption
3660 @param session: the active session to use
3661 """
3662
3663 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3664 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003665
3666 try:
Justin Thaler27197622019-01-23 14:42:11 -06003667 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003668 except(requests.exceptions.Timeout):
3669 return(connectionErrHandler(args.json, "Timeout", None))
3670 except(requests.exceptions.ConnectionError) as err:
3671 return connectionErrHandler(args.json, "ConnectionError", err)
3672 if res.status_code == 404:
3673 return "The specified Interface"+"("+args.Interface+")"+\
3674 " doesn't exist"
3675
3676 return res.text
3677
3678
3679def setMACAddress(host, args, session):
3680 """
3681 Called by the network function. Sets the MACAddress.
3682
3683 @param host: string, the hostname or IP address of the bmc
3684 @param args: contains additional arguments used by the ldap subcommand
3685 args.json: boolean, if this flag is set to true, the output
3686 will be provided in json format for programmatic consumption
3687 @param session: the active session to use
3688 """
3689
3690 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3691 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003692
3693 data = {"data": args.MACAddress}
3694
3695 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003696 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003697 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003698 except(requests.exceptions.Timeout):
3699 return(connectionErrHandler(args.json, "Timeout", None))
3700 except(requests.exceptions.ConnectionError) as err:
3701 return connectionErrHandler(args.json, "ConnectionError", err)
3702 if res.status_code == 403:
3703 return "The specified Interface"+"("+args.Interface+")"+\
3704 " doesn't exist"
3705
3706 return res.text
3707
3708
3709def getDefaultGateway(host, args, session):
3710
3711 """
3712 Called by the network function. Prints out the DefaultGateway.
3713
3714 @param host: string, the hostname or IP address of the bmc
3715 @param args: contains additional arguments used by the ldap subcommand
3716 args.json: boolean, if this flag is set to true, the output
3717 will be provided in json format for programmatic consumption
3718 @param session: the active session to use
3719 """
3720
3721 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003722
3723 try:
Justin Thaler27197622019-01-23 14:42:11 -06003724 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003725 except(requests.exceptions.Timeout):
3726 return(connectionErrHandler(args.json, "Timeout", None))
3727 except(requests.exceptions.ConnectionError) as err:
3728 return connectionErrHandler(args.json, "ConnectionError", err)
3729 if res.status_code == 404:
3730 return "Failed to get Default Gateway info!!"
3731
3732 return res.text
3733
3734
3735def setDefaultGateway(host, args, session):
3736 """
3737 Called by the network function. Sets the DefaultGateway.
3738
3739 @param host: string, the hostname or IP address of the bmc
3740 @param args: contains additional arguments used by the ldap subcommand
3741 args.json: boolean, if this flag is set to true, the output
3742 will be provided in json format for programmatic consumption
3743 @param session: the active session to use
3744 """
3745
3746 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003747
3748 data = {"data": args.DefaultGW}
3749
3750 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003751 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003752 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003753 except(requests.exceptions.Timeout):
3754 return(connectionErrHandler(args.json, "Timeout", None))
3755 except(requests.exceptions.ConnectionError) as err:
3756 return connectionErrHandler(args.json, "ConnectionError", err)
3757 if res.status_code == 403:
3758 return "Failed to set Default Gateway!!"
3759
3760 return res.text
3761
3762
3763def viewNWConfig(host, args, session):
3764 """
3765 Called by the ldap function. Prints out network configured properties
3766
3767 @param host: string, the hostname or IP address of the bmc
3768 @param args: contains additional arguments used by the ldap subcommand
3769 args.json: boolean, if this flag is set to true, the output
3770 will be provided in json format for programmatic consumption
3771 @param session: the active session to use
3772 @return returns LDAP's configured properties.
3773 """
3774 url = "https://"+host+"/xyz/openbmc_project/network/enumerate"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003775 try:
Justin Thaler27197622019-01-23 14:42:11 -06003776 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003777 except(requests.exceptions.Timeout):
3778 return(connectionErrHandler(args.json, "Timeout", None))
3779 except(requests.exceptions.ConnectionError) as err:
3780 return connectionErrHandler(args.json, "ConnectionError", err)
3781 except(requests.exceptions.RequestException) as err:
3782 return connectionErrHandler(args.json, "RequestException", err)
3783 if res.status_code == 404:
3784 return "LDAP server config has not been created"
3785 return res.text
3786
3787
3788def getDNS(host, args, session):
3789
3790 """
3791 Called by the network function. Prints out DNS servers on the interface
3792
3793 @param host: string, the hostname or IP address of the bmc
3794 @param args: contains additional arguments used by the ldap subcommand
3795 args.json: boolean, if this flag is set to true, the output
3796 will be provided in json format for programmatic consumption
3797 @param session: the active session to use
3798 """
3799
3800 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3801 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003802
3803 try:
Justin Thaler27197622019-01-23 14:42:11 -06003804 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003805 except(requests.exceptions.Timeout):
3806 return(connectionErrHandler(args.json, "Timeout", None))
3807 except(requests.exceptions.ConnectionError) as err:
3808 return connectionErrHandler(args.json, "ConnectionError", err)
3809 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003810 return "The NameServer is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003811
3812 return res.text
3813
3814
3815def setDNS(host, args, session):
3816 """
3817 Called by the network function. Sets DNS servers on the interface.
3818
3819 @param host: string, the hostname or IP address of the bmc
3820 @param args: contains additional arguments used by the ldap subcommand
3821 args.json: boolean, if this flag is set to true, the output
3822 will be provided in json format for programmatic consumption
3823 @param session: the active session to use
3824 """
3825
3826 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3827 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003828
3829 data = {"data": args.DNSServers.split(",")}
3830
3831 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003832 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003833 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -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 == 403:
3839 return "The specified Interface"+"("+args.Interface+")" +\
3840 " doesn't exist"
3841
3842 return res.text
3843
3844
3845def getNTP(host, args, session):
3846
3847 """
3848 Called by the network function. Prints out NTP servers on the interface
3849
3850 @param host: string, the hostname or IP address of the bmc
3851 @param args: contains additional arguments used by the ldap subcommand
3852 args.json: boolean, if this flag is set to true, the output
3853 will be provided in json format for programmatic consumption
3854 @param session: the active session to use
3855 """
3856
3857 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3858 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003859 try:
Justin Thaler27197622019-01-23 14:42:11 -06003860 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -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:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003866 return "The NTPServer is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003867
3868 return res.text
3869
3870
3871def setNTP(host, args, session):
3872 """
3873 Called by the network function. Sets NTP servers on the interface.
3874
3875 @param host: string, the hostname or IP address of the bmc
3876 @param args: contains additional arguments used by the ldap subcommand
3877 args.json: boolean, if this flag is set to true, the output
3878 will be provided in json format for programmatic consumption
3879 @param session: the active session to use
3880 """
3881
3882 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3883 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003884
3885 data = {"data": args.NTPServers.split(",")}
3886
3887 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003888 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003889 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003890 except(requests.exceptions.Timeout):
3891 return(connectionErrHandler(args.json, "Timeout", None))
3892 except(requests.exceptions.ConnectionError) as err:
3893 return connectionErrHandler(args.json, "ConnectionError", err)
3894 if res.status_code == 403:
3895 return "The specified Interface"+"("+args.Interface+")" +\
3896 " doesn't exist"
3897
3898 return res.text
3899
3900
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003901def addIP(host, args, session):
3902 """
3903 Called by the network function. Configures IP address on given interface
3904
3905 @param host: string, the hostname or IP address of the bmc
3906 @param args: contains additional arguments used by the ldap subcommand
3907 args.json: boolean, if this flag is set to true, the output
3908 will be provided in json format for programmatic consumption
3909 @param session: the active session to use
3910 """
3911
3912 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3913 + "/action/IP"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003914 protocol = {
3915 'ipv4': 'xyz.openbmc_project.Network.IP.Protocol.IPv4',
3916 'ipv6': 'xyz.openbmc_project.Network.IP.Protocol.IPv6'
3917 }
3918
3919 data = {"data": [protocol[args.type], args.address, int(args.prefixLength),
3920 args.gateway]}
3921
3922 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003923 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003924 timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003925 except(requests.exceptions.Timeout):
3926 return(connectionErrHandler(args.json, "Timeout", None))
3927 except(requests.exceptions.ConnectionError) as err:
3928 return connectionErrHandler(args.json, "ConnectionError", err)
3929 if res.status_code == 404:
3930 return "The specified Interface" + "(" + args.Interface + ")" +\
3931 " doesn't exist"
3932
3933 return res.text
3934
3935
3936def getIP(host, args, session):
3937 """
3938 Called by the network function. Prints out IP address of given interface
3939
3940 @param host: string, the hostname or IP address of the bmc
3941 @param args: contains additional arguments used by the ldap subcommand
3942 args.json: boolean, if this flag is set to true, the output
3943 will be provided in json format for programmatic consumption
3944 @param session: the active session to use
3945 """
3946
3947 url = "https://" + host+"/xyz/openbmc_project/network/" + args.Interface +\
3948 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003949 try:
Justin Thaler27197622019-01-23 14:42:11 -06003950 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003951 except(requests.exceptions.Timeout):
3952 return(connectionErrHandler(args.json, "Timeout", None))
3953 except(requests.exceptions.ConnectionError) as err:
3954 return connectionErrHandler(args.json, "ConnectionError", err)
3955 if res.status_code == 404:
3956 return "The specified Interface" + "(" + args.Interface + ")" +\
3957 " doesn't exist"
3958
3959 return res.text
3960
3961
3962def deleteIP(host, args, session):
3963 """
3964 Called by the network function. Deletes the IP address from given Interface
3965
3966 @param host: string, the hostname or IP address of the bmc
3967 @param args: contains additional arguments used by the ldap subcommand
3968 @param session: the active session to use
3969 @param args.json: boolean, if this flag is set to true, the output
3970 will be provided in json format for programmatic consumption
3971 """
3972
3973 url = "https://"+host+"/xyz/openbmc_project/network/" + args.Interface+\
3974 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003975 data = {"data": []}
3976 try:
Justin Thaler27197622019-01-23 14:42:11 -06003977 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003978 except(requests.exceptions.Timeout):
3979 return(connectionErrHandler(args.json, "Timeout", None))
3980 except(requests.exceptions.ConnectionError) as err:
3981 return connectionErrHandler(args.json, "ConnectionError", err)
3982 if res.status_code == 404:
3983 return "The specified Interface" + "(" + args.Interface + ")" +\
3984 " doesn't exist"
3985 objDict = json.loads(res.text)
3986 if not objDict['data']:
3987 return "No object found for given address on given Interface"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003988 for obj in objDict['data']:
Sunitha Harish0baf6372019-07-31 03:59:03 -05003989 try:
3990 if args.address in objDict['data'][obj]['Address']:
3991 url = "https://"+host+obj+"/action/Delete"
3992 try:
3993 res = session.post(url, headers=jsonHeader, json=data,
3994 verify=False, timeout=baseTimeout)
3995 except(requests.exceptions.Timeout):
3996 return(connectionErrHandler(args.json, "Timeout", None))
3997 except(requests.exceptions.ConnectionError) as err:
3998 return connectionErrHandler(args.json, "ConnectionError", err)
3999 return res.text
4000 else:
4001 continue
4002 except KeyError:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05004003 continue
4004 return "No object found for address " + args.address + \
4005 " on Interface(" + args.Interface + ")"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004006
4007
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004008def addVLAN(host, args, session):
4009 """
4010 Called by the network function. Creates VLAN on given interface.
4011
4012 @param host: string, the hostname or IP address of the bmc
4013 @param args: contains additional arguments used by the ldap subcommand
4014 args.json: boolean, if this flag is set to true, the output
4015 will be provided in json format for programmatic consumption
4016 @param session: the active session to use
4017 """
4018
4019 url = "https://" + host+"/xyz/openbmc_project/network/action/VLAN"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004020
Sunitha Harish0baf6372019-07-31 03:59:03 -05004021 data = {"data": [args.Interface,int(args.Identifier)]}
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004022 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06004023 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004024 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004025 except(requests.exceptions.Timeout):
4026 return(connectionErrHandler(args.json, "Timeout", None))
4027 except(requests.exceptions.ConnectionError) as err:
4028 return connectionErrHandler(args.json, "ConnectionError", err)
4029 if res.status_code == 400:
Sunitha Harish0baf6372019-07-31 03:59:03 -05004030 return "Adding VLAN to interface" + "(" + args.Interface + ")" +\
4031 " failed"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004032
4033 return res.text
4034
4035
4036def deleteVLAN(host, args, session):
4037 """
4038 Called by the network function. Creates VLAN on given interface.
4039
4040 @param host: string, the hostname or IP address of the bmc
4041 @param args: contains additional arguments used by the ldap subcommand
4042 args.json: boolean, if this flag is set to true, the output
4043 will be provided in json format for programmatic consumption
4044 @param session: the active session to use
4045 """
4046
Sunitha Harish577a5032019-08-08 06:27:40 -05004047 url = "https://" + host+"/xyz/openbmc_project/network/"+args.Interface+"/action/Delete"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004048 data = {"data": []}
4049
4050 try:
Justin Thaler27197622019-01-23 14:42:11 -06004051 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004052 except(requests.exceptions.Timeout):
4053 return(connectionErrHandler(args.json, "Timeout", None))
4054 except(requests.exceptions.ConnectionError) as err:
4055 return connectionErrHandler(args.json, "ConnectionError", err)
4056 if res.status_code == 404:
Sunitha Harish577a5032019-08-08 06:27:40 -05004057 return "The specified VLAN"+"("+args.Interface+")" +" doesn't exist"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004058
4059 return res.text
4060
4061
4062def viewDHCPConfig(host, args, session):
4063 """
4064 Called by the network function. Shows DHCP configured Properties.
4065
4066 @param host: string, the hostname or IP address of the bmc
4067 @param args: contains additional arguments used by the ldap subcommand
4068 args.json: boolean, if this flag is set to true, the output
4069 will be provided in json format for programmatic consumption
4070 @param session: the active session to use
4071 """
4072
4073 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004074
4075 try:
Justin Thaler27197622019-01-23 14:42:11 -06004076 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004077 except(requests.exceptions.Timeout):
4078 return(connectionErrHandler(args.json, "Timeout", None))
4079 except(requests.exceptions.ConnectionError) as err:
4080 return connectionErrHandler(args.json, "ConnectionError", err)
4081
4082 return res.text
4083
4084
4085def configureDHCP(host, args, session):
4086 """
4087 Called by the network function. Configures/updates DHCP Properties.
4088
4089 @param host: string, the hostname or IP address of the bmc
4090 @param args: contains additional arguments used by the ldap subcommand
4091 args.json: boolean, if this flag is set to true, the output
4092 will be provided in json format for programmatic consumption
4093 @param session: the active session to use
4094 """
4095
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004096
4097 try:
4098 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
4099 if(args.DNSEnabled == True):
4100 data = '{"data": 1}'
4101 else:
4102 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004103 res = session.put(url + '/attr/DNSEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004104 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004105 if(args.HostNameEnabled == True):
4106 data = '{"data": 1}'
4107 else:
4108 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004109 res = session.put(url + '/attr/HostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004110 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004111 if(args.NTPEnabled == True):
4112 data = '{"data": 1}'
4113 else:
4114 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004115 res = session.put(url + '/attr/NTPEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004116 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004117 if(args.SendHostNameEnabled == True):
4118 data = '{"data": 1}'
4119 else:
4120 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06004121 res = session.put(url + '/attr/SendHostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06004122 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004123 except(requests.exceptions.Timeout):
4124 return(connectionErrHandler(args.json, "Timeout", None))
4125 except(requests.exceptions.ConnectionError) as err:
4126 return connectionErrHandler(args.json, "ConnectionError", err)
4127
4128 return res.text
4129
4130
4131def nwReset(host, args, session):
4132
4133 """
4134 Called by the network function. Resets networks setting to factory defaults.
4135
4136 @param host: string, the hostname or IP address of the bmc
4137 @param args: contains additional arguments used by the ldap subcommand
4138 args.json: boolean, if this flag is set to true, the output
4139 will be provided in json format for programmatic consumption
4140 @param session: the active session to use
4141 """
4142
4143 url = "https://"+host+"/xyz/openbmc_project/network/action/Reset"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004144 data = '{"data":[] }'
4145 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06004146 res = session.post(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004147 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004148
4149 except(requests.exceptions.Timeout):
4150 return(connectionErrHandler(args.json, "Timeout", None))
4151 except(requests.exceptions.ConnectionError) as err:
4152 return connectionErrHandler(args.json, "ConnectionError", err)
4153
4154 return res.text
4155
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004156def getLDAPTypeEnabled(host,session):
4157
4158 """
4159 Called by LDAP related functions to find the LDAP server type that has been enabled.
4160 Returns None if LDAP has not been configured.
4161
4162 @param host: string, the hostname or IP address of the bmc
4163 @param session: the active session to use
4164 """
4165
4166 enabled = False
4167 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
4168 for key,value in serverTypeMap.items():
4169 data = {"data": []}
4170 try:
4171 res = session.get(url + value + '/attr/Enabled', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4172 except(requests.exceptions.Timeout):
4173 print(connectionErrHandler(args.json, "Timeout", None))
4174 return
4175 except(requests.exceptions.ConnectionError) as err:
4176 print(connectionErrHandler(args.json, "ConnectionError", err))
4177 return
4178
4179 enabled = res.json()['data']
4180 if (enabled):
4181 return key
4182
4183def syncRoleMap(host,args,session,fromServerType,toServerType):
4184
4185 """
4186 Called by LDAP related functions to sync the role maps
4187 Returns False if LDAP has not been configured.
4188
4189 @param host: string, the hostname or IP address of the bmc
4190 @param session: the active session to use
4191 @param fromServerType : Server type whose role map has to be copied
4192 @param toServerType : Server type to which role map has to be copied
4193 """
4194
4195 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
4196
4197 try:
4198 #Note: If the fromServerType has no role map, then
4199 #the toServerType will not have any role map.
4200
4201 #delete the privilege mapping from the toServerType and
4202 #then copy the privilege mapping from fromServerType to
4203 #toServerType.
4204 args.serverType = toServerType
4205 res = deleteAllPrivilegeMapping(host, args, session)
4206
4207 data = {"data": []}
4208 res = session.get(url + serverTypeMap[fromServerType] + '/role_map/enumerate', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4209 #Previously enabled server type has no role map
4210 if (res.status_code != requests.codes.ok):
4211
4212 #fromServerType has no role map; So, no need to copy
4213 #role map to toServerType.
4214 return
4215
4216 objDict = json.loads(res.text)
4217 dataDict = objDict['data']
4218 for key,value in dataDict.items():
4219 data = {"data": [value["GroupName"], value["Privilege"]]}
4220 res = session.post(url + serverTypeMap[toServerType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4221
4222 except(requests.exceptions.Timeout):
4223 return(connectionErrHandler(args.json, "Timeout", None))
4224 except(requests.exceptions.ConnectionError) as err:
4225 return connectionErrHandler(args.json, "ConnectionError", err)
4226 return res.text
4227
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004228
Ratan Guptafeee6372018-10-17 23:25:51 +05304229def createPrivilegeMapping(host, args, session):
4230 """
4231 Called by the ldap function. Creates the group and the privilege mapping.
4232
4233 @param host: string, the hostname or IP address of the bmc
4234 @param args: contains additional arguments used by the ldap subcommand
4235 @param session: the active session to use
4236 @param args.json: boolean, if this flag is set to true, the output
4237 will be provided in json format for programmatic consumption
4238 """
4239
Ratan Guptafeee6372018-10-17 23:25:51 +05304240 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004241 if (isRedfishSupport):
4242 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
4243
4244 #To maintain the interface compatibility between op930 and op940, the server type has been made
4245 #optional. If the server type is not specified, then create the role-mapper for the currently
4246 #enabled server type.
4247 serverType = args.serverType
4248 if (serverType is None):
4249 serverType = getLDAPTypeEnabled(host,session)
4250 if (serverType is None):
4251 return("LDAP server has not been enabled. Please specify LDAP serverType to proceed further...")
4252
4253 data = {"data": [args.groupName,args.privilege]}
4254 res = session.post(url + serverTypeMap[serverType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4255
4256 else:
4257 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/action/Create'
4258 data = {"data": [args.groupName,args.privilege]}
4259 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4260
Ratan Guptafeee6372018-10-17 23:25:51 +05304261 except(requests.exceptions.Timeout):
4262 return(connectionErrHandler(args.json, "Timeout", None))
4263 except(requests.exceptions.ConnectionError) as err:
4264 return connectionErrHandler(args.json, "ConnectionError", err)
4265 return res.text
4266
4267def listPrivilegeMapping(host, args, session):
4268 """
4269 Called by the ldap function. Lists the group and the privilege mapping.
4270
4271 @param host: string, the hostname or IP address of the bmc
4272 @param args: contains additional arguments used by the ldap subcommand
4273 @param session: the active session to use
4274 @param args.json: boolean, if this flag is set to true, the output
4275 will be provided in json format for programmatic consumption
4276 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004277
4278 if (isRedfishSupport):
4279 serverType = args.serverType
4280 if (serverType is None):
4281 serverType = getLDAPTypeEnabled(host,session)
4282 if (serverType is None):
4283 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4284
4285 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'+serverTypeMap[serverType]+'/role_map/enumerate'
4286
4287 else:
4288 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/enumerate'
4289
Ratan Guptafeee6372018-10-17 23:25:51 +05304290 data = {"data": []}
4291
4292 try:
Justin Thaler27197622019-01-23 14:42:11 -06004293 res = session.get(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05304294 except(requests.exceptions.Timeout):
4295 return(connectionErrHandler(args.json, "Timeout", None))
4296 except(requests.exceptions.ConnectionError) as err:
4297 return connectionErrHandler(args.json, "ConnectionError", err)
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004298
Ratan Guptafeee6372018-10-17 23:25:51 +05304299 return res.text
4300
4301def deletePrivilegeMapping(host, args, session):
4302 """
4303 Called by the ldap function. Deletes the mapping associated with the group.
4304
4305 @param host: string, the hostname or IP address of the bmc
4306 @param args: contains additional arguments used by the ldap subcommand
4307 @param session: the active session to use
4308 @param args.json: boolean, if this flag is set to true, the output
4309 will be provided in json format for programmatic consumption
4310 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004311
4312 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
Ratan Guptafeee6372018-10-17 23:25:51 +05304313 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
4314 path = ''
Ratan Guptafeee6372018-10-17 23:25:51 +05304315 data = {"data": []}
4316
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004317 if (isRedfishSupport):
4318 if (args.serverType is None):
4319 serverType = getLDAPTypeEnabled(host,session)
4320 if (serverType is None):
4321 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4322 # search for the object having the mapping for the given group
4323 for key,value in ldapNameSpaceObjects.items():
4324 if value['GroupName'] == args.groupName:
4325 path = key
4326 break
4327
4328 if path == '':
4329 return "No privilege mapping found for this group."
4330
4331 # delete the object
4332 url = 'https://'+host+path+'/action/Delete'
4333
4334 else:
4335 # not interested in the config objet
4336 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
4337
4338 # search for the object having the mapping for the given group
4339 for key,value in ldapNameSpaceObjects.items():
4340 if value['GroupName'] == args.groupName:
4341 path = key
4342 break
4343
4344 if path == '':
4345 return "No privilege mapping found for this group."
4346
4347 # delete the object
4348 url = 'https://'+host+path+'/action/delete'
4349
Ratan Guptafeee6372018-10-17 23:25:51 +05304350 try:
Justin Thaler27197622019-01-23 14:42:11 -06004351 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05304352 except(requests.exceptions.Timeout):
4353 return(connectionErrHandler(args.json, "Timeout", None))
4354 except(requests.exceptions.ConnectionError) as err:
4355 return connectionErrHandler(args.json, "ConnectionError", err)
4356 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05304357
Sivas SRR78835272018-11-27 05:27:19 -06004358def deleteAllPrivilegeMapping(host, args, session):
4359 """
4360 Called by the ldap function. Deletes all the privilege mapping and group defined.
4361 @param host: string, the hostname or IP address of the bmc
4362 @param args: contains additional arguments used by the ldap subcommand
4363 @param session: the active session to use
4364 @param args.json: boolean, if this flag is set to true, the output
4365 will be provided in json format for programmatic consumption
4366 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004367
Sivas SRR78835272018-11-27 05:27:19 -06004368 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
4369 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
4370 path = ''
Sivas SRR78835272018-11-27 05:27:19 -06004371 data = {"data": []}
4372
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004373 if (isRedfishSupport):
4374 if (args.serverType is None):
4375 serverType = getLDAPTypeEnabled(host,session)
4376 if (serverType is None):
4377 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4378
4379 else:
4380 # Remove the config object.
4381 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
4382
Sivas SRR78835272018-11-27 05:27:19 -06004383 try:
4384 # search for GroupName property and delete if it is available.
4385 for path in ldapNameSpaceObjects.keys():
4386 # delete the object
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004387 url = 'https://'+host+path+'/action/Delete'
Justin Thaler27197622019-01-23 14:42:11 -06004388 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004389
Sivas SRR78835272018-11-27 05:27:19 -06004390 except(requests.exceptions.Timeout):
4391 return(connectionErrHandler(args.json, "Timeout", None))
4392 except(requests.exceptions.ConnectionError) as err:
4393 return connectionErrHandler(args.json, "ConnectionError", err)
4394 return res.text
4395
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004396def viewLDAPConfig(host, args, session):
4397 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004398 Called by the ldap function. Prints out active LDAP configuration properties
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004399
4400 @param host: string, the hostname or IP address of the bmc
4401 @param args: contains additional arguments used by the ldap subcommand
4402 args.json: boolean, if this flag is set to true, the output
4403 will be provided in json format for programmatic consumption
4404 @param session: the active session to use
4405 @return returns LDAP's configured properties.
4406 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004407
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004408 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004409 if (isRedfishSupport):
4410
4411 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
4412
4413 serverTypeEnabled = getLDAPTypeEnabled(host,session)
4414
4415 if (serverTypeEnabled is not None):
4416 data = {"data": []}
4417 res = session.get(url + serverTypeMap[serverTypeEnabled], headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4418 else:
4419 return("LDAP server has not been enabled...")
4420
4421 else :
4422 url = "https://"+host+"/xyz/openbmc_project/user/ldap/config"
4423 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
4424
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004425 except(requests.exceptions.Timeout):
4426 return(connectionErrHandler(args.json, "Timeout", None))
4427 except(requests.exceptions.ConnectionError) as err:
4428 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004429 if res.status_code == 404:
4430 return "LDAP server config has not been created"
4431 return res.text
4432
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004433def str2bool(v):
4434 if v.lower() in ('yes', 'true', 't', 'y', '1'):
4435 return True
4436 elif v.lower() in ('no', 'false', 'f', 'n', '0'):
4437 return False
4438 else:
4439 raise argparse.ArgumentTypeError('Boolean value expected.')
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004440
Matt Spinler7d426c22018-09-24 14:42:07 -05004441def localUsers(host, args, session):
4442 """
4443 Enables and disables local BMC users.
4444
4445 @param host: string, the hostname or IP address of the bmc
4446 @param args: contains additional arguments used by the logging sub command
4447 @param session: the active session to use
4448 """
4449
Matt Spinler7d426c22018-09-24 14:42:07 -05004450 url="https://{hostname}/xyz/openbmc_project/user/enumerate".format(hostname=host)
4451 try:
Justin Thaler27197622019-01-23 14:42:11 -06004452 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004453 except(requests.exceptions.Timeout):
4454 return(connectionErrHandler(args.json, "Timeout", None))
4455 usersDict = json.loads(res.text)
4456
4457 if not usersDict['data']:
4458 return "No users found"
4459
4460 output = ""
4461 for user in usersDict['data']:
Matt Spinler015adc22018-10-23 14:30:19 -05004462
4463 # Skip LDAP and another non-local users
4464 if 'UserEnabled' not in usersDict['data'][user]:
4465 continue
4466
Matt Spinler7d426c22018-09-24 14:42:07 -05004467 name = user.split('/')[-1]
4468 url = "https://{hostname}{user}/attr/UserEnabled".format(hostname=host, user=user)
4469
4470 if args.local_users == "queryenabled":
4471 try:
Justin Thaler27197622019-01-23 14:42:11 -06004472 res = session.get(url, headers=jsonHeader,verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004473 except(requests.exceptions.Timeout):
4474 return(connectionErrHandler(args.json, "Timeout", None))
4475
4476 result = json.loads(res.text)
4477 output += ("User: {name} Enabled: {result}\n").format(name=name, result=result['data'])
4478
4479 elif args.local_users in ["enableall", "disableall"]:
4480 action = ""
4481 if args.local_users == "enableall":
4482 data = '{"data": true}'
4483 action = "Enabling"
4484 else:
4485 data = '{"data": false}'
4486 action = "Disabling"
4487
4488 output += "{action} {name}\n".format(action=action, name=name)
4489
4490 try:
Justin Thaler27197622019-01-23 14:42:11 -06004491 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004492 except(requests.exceptions.Timeout):
4493 return connectionErrHandler(args.json, "Timeout", None)
4494 except(requests.exceptions.ConnectionError) as err:
4495 return connectionErrHandler(args.json, "ConnectionError", err)
4496 else:
4497 return "Invalid local users argument"
4498
4499 return output
4500
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004501def setPassword(host, args, session):
4502 """
4503 Set local user password
4504 @param host: string, the hostname or IP address of the bmc
4505 @param args: contains additional arguments used by the logging sub
4506 command
4507 @param session: the active session to use
4508 @param args.json: boolean, if this flag is set to true, the output
4509 will be provided in json format for programmatic consumption
4510 @return: Session object
4511 """
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004512 try:
Sunitha Harishc99faba2019-07-19 06:55:22 -05004513 if(isRedfishSupport):
4514 url = "https://" + host + "/redfish/v1/AccountService/Accounts/"+ \
4515 args.user
4516 data = {"Password":args.password}
4517 res = session.patch(url, headers=jsonHeader, json=data,
4518 verify=False, timeout=baseTimeout)
4519 else:
4520 url = "https://" + host + "/xyz/openbmc_project/user/" + args.user + \
4521 "/action/SetPassword"
4522 res = session.post(url, headers=jsonHeader,
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004523 json={"data": [args.password]}, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004524 timeout=baseTimeout)
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004525 except(requests.exceptions.Timeout):
4526 return(connectionErrHandler(args.json, "Timeout", None))
4527 except(requests.exceptions.ConnectionError) as err:
4528 return connectionErrHandler(args.json, "ConnectionError", err)
4529 except(requests.exceptions.RequestException) as err:
4530 return connectionErrHandler(args.json, "RequestException", err)
Sunitha Harishc99faba2019-07-19 06:55:22 -05004531 return res.status_code
Matthew Barth368e83c2019-02-01 13:48:25 -06004532
4533def getThermalZones(host, args, session):
4534 """
4535 Get the available thermal control zones
4536 @param host: string, the hostname or IP address of the bmc
4537 @param args: contains additional arguments used to get the thermal
4538 control zones
4539 @param session: the active session to use
4540 @return: Session object
4541 """
4542 url = "https://" + host + "/xyz/openbmc_project/control/thermal/enumerate"
4543
4544 try:
4545 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4546 except(requests.exceptions.Timeout):
4547 return(connectionErrHandler(args.json, "Timeout", None))
4548 except(requests.exceptions.ConnectionError) as err:
4549 return connectionErrHandler(args.json, "ConnectionError", err)
4550 except(requests.exceptions.RequestException) as err:
4551 return connectionErrHandler(args.json, "RequestException", err)
4552
4553 if (res.status_code == 404):
Matthew Barth0939e822019-09-27 15:47:50 -05004554 return "No thermal control zones found"
Matthew Barth368e83c2019-02-01 13:48:25 -06004555
4556 zonesDict = json.loads(res.text)
4557 if not zonesDict['data']:
4558 return "No thermal control zones found"
4559 for zone in zonesDict['data']:
4560 z = ",".join(str(zone.split('/')[-1]) for zone in zonesDict['data'])
4561
4562 return "Zones: [ " + z + " ]"
4563
4564
4565def getThermalMode(host, args, session):
4566 """
4567 Get thermal control mode
4568 @param host: string, the hostname or IP address of the bmc
4569 @param args: contains additional arguments used to get the thermal
4570 control mode
4571 @param session: the active session to use
4572 @param args.zone: the zone to get the mode on
4573 @return: Session object
4574 """
4575 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
4576 args.zone
4577
4578 try:
4579 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4580 except(requests.exceptions.Timeout):
4581 return(connectionErrHandler(args.json, "Timeout", None))
4582 except(requests.exceptions.ConnectionError) as err:
4583 return connectionErrHandler(args.json, "ConnectionError", err)
4584 except(requests.exceptions.RequestException) as err:
4585 return connectionErrHandler(args.json, "RequestException", err)
4586
4587 if (res.status_code == 404):
Matthew Barth0939e822019-09-27 15:47:50 -05004588 return "Thermal control zone(" + args.zone + ") not found"
Matthew Barth368e83c2019-02-01 13:48:25 -06004589
4590 propsDict = json.loads(res.text)
4591 if not propsDict['data']:
4592 return "No thermal control properties found on zone(" + args.zone + ")"
4593 curMode = "Current"
4594 supModes = "Supported"
4595 result = "\n"
4596 for prop in propsDict['data']:
4597 if (prop.casefold() == curMode.casefold()):
4598 result += curMode + " Mode: " + propsDict['data'][curMode] + "\n"
4599 if (prop.casefold() == supModes.casefold()):
4600 s = ", ".join(str(sup) for sup in propsDict['data'][supModes])
4601 result += supModes + " Modes: [ " + s + " ]\n"
4602
4603 return result
4604
4605def setThermalMode(host, args, session):
4606 """
4607 Set thermal control mode
4608 @param host: string, the hostname or IP address of the bmc
4609 @param args: contains additional arguments used for setting the thermal
4610 control mode
4611 @param session: the active session to use
4612 @param args.zone: the zone to set the mode on
4613 @param args.mode: the mode to enable
4614 @return: Session object
4615 """
4616 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
4617 args.zone + "/attr/Current"
4618
4619 # Check args.mode against supported modes using `getThermalMode` output
4620 modes = getThermalMode(host, args, session)
4621 modes = os.linesep.join([m for m in modes.splitlines() if m])
4622 modes = modes.replace("\n", ";").strip()
4623 modesDict = dict(m.split(': ') for m in modes.split(';'))
4624 sModes = ''.join(s for s in modesDict['Supported Modes'] if s not in '[ ]')
4625 if args.mode.casefold() not in \
4626 (m.casefold() for m in sModes.split(',')) or not args.mode:
4627 result = ("Unsupported mode('" + args.mode + "') given, " +
4628 "select a supported mode: \n" +
4629 getThermalMode(host, args, session))
4630 return result
4631
4632 data = '{"data":"' + args.mode + '"}'
4633 try:
4634 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4635 except(requests.exceptions.Timeout):
4636 return(connectionErrHandler(args.json, "Timeout", None))
4637 except(requests.exceptions.ConnectionError) as err:
4638 return connectionErrHandler(args.json, "ConnectionError", err)
4639 except(requests.exceptions.RequestException) as err:
4640 return connectionErrHandler(args.json, "RequestException", err)
4641
4642 if (data and res.status_code != 404):
4643 try:
4644 res = session.put(url, headers=jsonHeader,
4645 data=data, verify=False,
4646 timeout=30)
4647 except(requests.exceptions.Timeout):
4648 return(connectionErrHandler(args.json, "Timeout", None))
4649 except(requests.exceptions.ConnectionError) as err:
4650 return connectionErrHandler(args.json, "ConnectionError", err)
4651 except(requests.exceptions.RequestException) as err:
4652 return connectionErrHandler(args.json, "RequestException", err)
4653
4654 if res.status_code == 403:
4655 return "The specified thermal control zone(" + args.zone + ")" + \
4656 " does not exist"
4657
4658 return res.text
4659 else:
4660 return "Setting thermal control mode(" + args.mode + ")" + \
Matthew Barth0939e822019-09-27 15:47:50 -05004661 " not supported or operation not available"
Matthew Barth368e83c2019-02-01 13:48:25 -06004662
4663
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004664def createCommandParser():
Justin Thalere412dc22018-01-12 16:28:24 -06004665 """
4666 creates the parser for the command line along with help for each command and subcommand
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004667
Justin Thalere412dc22018-01-12 16:28:24 -06004668 @return: returns the parser for the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004669 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004670 parser = argparse.ArgumentParser(description='Process arguments')
Justin Thalere412dc22018-01-12 16:28:24 -06004671 parser.add_argument("-H", "--host", help='A hostname or IP for the BMC')
4672 parser.add_argument("-U", "--user", help='The username to login with')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004673 group = parser.add_mutually_exclusive_group()
4674 group.add_argument("-A", "--askpw", action='store_true', help='prompt for password')
4675 group.add_argument("-P", "--PW", help='Provide the password in-line')
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05004676 group.add_argument("-E", "--PWenvvar", action='store_true', help='Get password from envvar OPENBMCTOOL_PASSWORD')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004677 parser.add_argument('-j', '--json', action='store_true', help='output json data only')
4678 parser.add_argument('-t', '--policyTableLoc', help='The location of the policy table to parse alerts')
4679 parser.add_argument('-c', '--CerFormat', action='store_true', help=argparse.SUPPRESS)
4680 parser.add_argument('-T', '--procTime', action='store_true', help= argparse.SUPPRESS)
Justin Thalere412dc22018-01-12 16:28:24 -06004681 parser.add_argument('-V', '--version', action='store_true', help='Display the version number of the openbmctool')
4682 subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004683
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004684 #fru command
4685 parser_inv = subparsers.add_parser("fru", help='Work with platform inventory')
Justin Thalere412dc22018-01-12 16:28:24 -06004686 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 -05004687 inv_subparser.required = True
4688 #fru print
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004689 inv_print = inv_subparser.add_parser("print", help="prints out a list of all FRUs")
4690 inv_print.set_defaults(func=fruPrint)
4691 #fru list [0....n]
4692 inv_list = inv_subparser.add_parser("list", help="print out details on selected FRUs. Specifying no items will list the entire inventory")
4693 inv_list.add_argument('items', nargs='?', help="print out details on selected FRUs. Specifying no items will list the entire inventory")
4694 inv_list.set_defaults(func=fruList)
4695 #fru status
4696 inv_status = inv_subparser.add_parser("status", help="prints out the status of all FRUs")
Justin Thalere412dc22018-01-12 16:28:24 -06004697 inv_status.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004698 inv_status.set_defaults(func=fruStatus)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004699
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004700 #sensors command
4701 parser_sens = subparsers.add_parser("sensors", help="Work with platform sensors")
Justin Thalere412dc22018-01-12 16:28:24 -06004702 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 -05004703 sens_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004704 #sensor print
4705 sens_print= sens_subparser.add_parser('print', help="prints out a list of all Sensors.")
4706 sens_print.set_defaults(func=sensor)
4707 #sensor list[0...n]
4708 sens_list=sens_subparser.add_parser("list", help="Lists all Sensors in the platform. Specify a sensor for full details. ")
4709 sens_list.add_argument("sensNum", nargs='?', help="The Sensor number to get full details on" )
4710 sens_list.set_defaults(func=sensor)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004711
Matthew Barth368e83c2019-02-01 13:48:25 -06004712 #thermal control commands
4713 parser_therm = subparsers.add_parser("thermal", help="Work with thermal control parameters")
4714 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')
4715 #thermal control zones
4716 parser_thermZones = therm_subparser.add_parser("zones", help="Get a list of available thermal control zones")
4717 parser_thermZones.set_defaults(func=getThermalZones)
4718 #thermal control modes
4719 parser_thermMode = therm_subparser.add_parser("modes", help="Work with thermal control modes")
4720 thermMode_sub = parser_thermMode.add_subparsers(title='subactions', description='Work with thermal control modes', help="Work with thermal control modes")
4721 #get thermal control mode
4722 parser_getThermMode = thermMode_sub.add_parser("get", help="Get current and supported thermal control modes")
4723 parser_getThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
4724 parser_getThermMode.set_defaults(func=getThermalMode)
4725 #set thermal control mode
4726 parser_setThermMode = thermMode_sub.add_parser("set", help="Set the thermal control mode")
4727 parser_setThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
4728 parser_setThermMode.add_argument('-m', '--mode', required=True, help='The supported thermal control mode')
4729 parser_setThermMode.set_defaults(func=setThermalMode)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004730
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004731 #sel command
4732 parser_sel = subparsers.add_parser("sel", help="Work with platform alerts")
Justin Thalere412dc22018-01-12 16:28:24 -06004733 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 -05004734 sel_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004735 #sel print
4736 sel_print = sel_subparser.add_parser("print", help="prints out a list of all sels in a condensed list")
4737 sel_print.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
4738 sel_print.add_argument('-v', '--verbose', action='store_true', help="Changes the output to being very verbose")
4739 sel_print.add_argument('-f', '--fileloc', help='Parse a file instead of the BMC output')
4740 sel_print.set_defaults(func=selPrint)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004741
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004742 #sel list
4743 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")
4744 sel_list.add_argument("selNum", nargs='?', type=int, help="The SEL entry to get details on")
4745 sel_list.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004746
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004747 sel_get = sel_subparser.add_parser("get", help="Gets the verbose details of a specified SEL entry")
4748 sel_get.add_argument('selNum', type=int, help="the number of the SEL entry to get")
4749 sel_get.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004750
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004751 sel_clear = sel_subparser.add_parser("clear", help="Clears all entries from the SEL")
4752 sel_clear.set_defaults(func=selClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004753
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004754 sel_setResolved = sel_subparser.add_parser("resolve", help="Sets the sel entry to resolved")
Justin Thalere412dc22018-01-12 16:28:24 -06004755 sel_setResolved.add_argument('-n', '--selNum', type=int, help="the number of the SEL entry to resolve")
4756 sel_ResolveAll_sub = sel_setResolved.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
4757 sel_ResolveAll = sel_ResolveAll_sub.add_parser('all', help='Resolve all SEL entries')
4758 sel_ResolveAll.set_defaults(func=selResolveAll)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004759 sel_setResolved.set_defaults(func=selSetResolved)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004760
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004761 parser_chassis = subparsers.add_parser("chassis", help="Work with chassis power and status")
Justin Thalere412dc22018-01-12 16:28:24 -06004762 chas_sub = parser_chassis.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004763
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004764 parser_chassis.add_argument('status', action='store_true', help='Returns the current status of the platform')
4765 parser_chassis.set_defaults(func=chassis)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004766
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004767 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 -06004768 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 -06004769 parser_chasPower.set_defaults(func=chassisPower)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004770
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004771 #control the chassis identify led
4772 parser_chasIdent = chas_sub.add_parser("identify", help="Control the chassis identify led")
4773 parser_chasIdent.add_argument('identcmd', choices=['on', 'off', 'status'], help='The control option for the led: on, off, blink, status')
4774 parser_chasIdent.set_defaults(func=chassisIdent)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004775
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004776 #collect service data
4777 parser_servData = subparsers.add_parser("collect_service_data", help="Collect all bmc data needed for service")
4778 parser_servData.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
4779 parser_servData.set_defaults(func=collectServiceData)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004780
Justin Thalere412dc22018-01-12 16:28:24 -06004781 #system quick health check
4782 parser_healthChk = subparsers.add_parser("health_check", help="Work with platform sensors")
4783 parser_healthChk.set_defaults(func=healthCheck)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004784
Ravi Tejad8be0b42020-03-18 14:31:46 -05004785 #work with dumps
4786 parser_bmcdump = subparsers.add_parser("dump", help="Work with dumps")
4787 parser_bmcdump.add_argument("-t", "--dumpType", default='bmc', choices=['bmc','SystemDump'],help="Type of dump")
Justin Thalere412dc22018-01-12 16:28:24 -06004788 bmcDump_sub = parser_bmcdump.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thaler53bf2f12018-07-16 14:05:32 -05004789 bmcDump_sub.required = True
Ravi Tejad8be0b42020-03-18 14:31:46 -05004790 dump_Create = bmcDump_sub.add_parser('create', help="Create a dump of given type")
4791 dump_Create.set_defaults(func=dumpCreate)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004792
Ravi Tejad8be0b42020-03-18 14:31:46 -05004793 dump_list = bmcDump_sub.add_parser('list', help="list all dumps")
4794 dump_list.set_defaults(func=dumpList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004795
Ravi Tejad8be0b42020-03-18 14:31:46 -05004796 parserdumpdelete = bmcDump_sub.add_parser('delete', help="Delete dump")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004797 parserdumpdelete.add_argument("-n", "--dumpNum", nargs='*', type=int, help="The Dump entry to delete")
Ravi Tejad8be0b42020-03-18 14:31:46 -05004798 parserdumpdelete.set_defaults(func=dumpDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004799
Justin Thalere412dc22018-01-12 16:28:24 -06004800 bmcDumpDelsub = parserdumpdelete.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Ravi Tejad8be0b42020-03-18 14:31:46 -05004801 deleteAllDumps = bmcDumpDelsub.add_parser('all', help='Delete all dumps')
4802 deleteAllDumps.set_defaults(func=dumpDeleteAll)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004803
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004804 parser_dumpretrieve = bmcDump_sub.add_parser('retrieve', help='Retrieve a dump file')
Ravi Tejad8be0b42020-03-18 14:31:46 -05004805 parser_dumpretrieve.add_argument("-n,", "--dumpNum", help="The Dump entry to retrieve")
4806 parser_dumpretrieve.add_argument("-s", "--dumpSaveLoc", help="The location to save the bmc dump file or file path for system dump")
4807 parser_dumpretrieve.set_defaults(func=dumpRetrieve)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004808
Justin Thaler22b1bb52018-03-15 13:31:32 -05004809 #bmc command for reseting the bmc
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004810 parser_bmc = subparsers.add_parser('bmc', help="Work with the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004811 bmc_sub = parser_bmc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004812 parser_BMCReset = bmc_sub.add_parser('reset', help='Reset the bmc' )
4813 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 -06004814 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.")
4815 parser_bmc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004816
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004817 #add alias to the bmc command
4818 parser_mc = subparsers.add_parser('mc', help="Work with the management controller")
Justin Thalere412dc22018-01-12 16:28:24 -06004819 mc_sub = parser_mc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004820 parser_MCReset = mc_sub.add_parser('reset', help='Reset the bmc' )
4821 parser_MCReset.add_argument('type', choices=['warm','cold'], help="Reboot the BMC")
4822 #parser_MCReset.add_argument('cold', action='store_true', help="Reboot the BMC and CLEAR the configuration")
4823 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 -06004824 parser_MCReset.set_defaults(func=bmcReset)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004825 parser_mc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004826
Justin Thalere412dc22018-01-12 16:28:24 -06004827 #gard clear
4828 parser_gc = subparsers.add_parser("gardclear", help="Used to clear gard records")
4829 parser_gc.set_defaults(func=gardClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004830
Justin Thalere412dc22018-01-12 16:28:24 -06004831 #firmware_flash
4832 parser_fw = subparsers.add_parser("firmware", help="Work with the system firmware")
4833 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 -05004834 fwflash_subproc.required = True
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004835
Justin Thalere412dc22018-01-12 16:28:24 -06004836 fwflash = fwflash_subproc.add_parser('flash', help="Flash the system firmware")
4837 fwflash.add_argument('type', choices=['bmc', 'pnor'], help="image type to flash")
4838 fwflash.add_argument('-f', '--fileloc', required=True, help="The absolute path to the firmware image")
4839 fwflash.set_defaults(func=fwFlash)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004840
Justin Thaler22b1bb52018-03-15 13:31:32 -05004841 fwActivate = fwflash_subproc.add_parser('activate', help="Activate existing image on the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004842 fwActivate.add_argument('imageID', help="The image ID to activate from the firmware list. Ex: 63c95399")
4843 fwActivate.set_defaults(func=activateFWImage)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004844
Justin Thaler22b1bb52018-03-15 13:31:32 -05004845 fwActivateStatus = fwflash_subproc.add_parser('activation_status', help="Check Status of activations")
4846 fwActivateStatus.set_defaults(func=activateStatus)
4847
Justin Thaler3d71d402018-07-24 14:35:39 -05004848 fwList = fwflash_subproc.add_parser('list', help="List all of the installed firmware")
4849 fwList.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4850 fwList.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004851
Justin Thaler3d71d402018-07-24 14:35:39 -05004852 fwprint = fwflash_subproc.add_parser('print', help="List all of the installed firmware")
4853 fwprint.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4854 fwprint.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004855
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06004856 fwDelete = fwflash_subproc.add_parser('delete', help="Delete an existing firmware version")
4857 fwDelete.add_argument('versionID', help="The version ID to delete from the firmware list. Ex: 63c95399")
4858 fwDelete.set_defaults(func=deleteFWVersion)
4859
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004860 #logging
4861 parser_logging = subparsers.add_parser("logging", help="logging controls")
4862 logging_sub = parser_logging.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004863
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004864 #turn rest api logging on/off
4865 parser_rest_logging = logging_sub.add_parser("rest_api", help="turn rest api logging on/off")
4866 parser_rest_logging.add_argument('rest_logging', choices=['on', 'off'], help='The control option for rest logging: on, off')
4867 parser_rest_logging.set_defaults(func=restLogging)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05004868
4869 #remote logging
4870 parser_remote_logging = logging_sub.add_parser("remote_logging", help="Remote logging (rsyslog) commands")
4871 parser_remote_logging.add_argument('remote_logging', choices=['view', 'disable'], help='Remote logging (rsyslog) commands')
4872 parser_remote_logging.set_defaults(func=remoteLogging)
4873
4874 #configure remote logging
4875 parser_remote_logging_config = logging_sub.add_parser("remote_logging_config", help="Configure remote logging (rsyslog)")
4876 parser_remote_logging_config.add_argument("-a", "--address", required=True, help="Set IP address of rsyslog server")
4877 parser_remote_logging_config.add_argument("-p", "--port", required=True, type=int, help="Set Port of rsyslog server")
4878 parser_remote_logging_config.set_defaults(func=remoteLoggingConfig)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05004879
4880 #certificate management
4881 parser_cert = subparsers.add_parser("certificate", help="Certificate management")
4882 certMgmt_subproc = parser_cert.add_subparsers(title='subcommands', description='valid certificate commands', help='sub-command help', dest='command')
4883
4884 certUpdate = certMgmt_subproc.add_parser('update', help="Update the certificate")
4885 certUpdate.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to update")
4886 certUpdate.add_argument('service', choices=['https', 'ldap'], help="Service to update")
4887 certUpdate.add_argument('-f', '--fileloc', required=True, help="The absolute path to the certificate file")
4888 certUpdate.set_defaults(func=certificateUpdate)
4889
4890 certDelete = certMgmt_subproc.add_parser('delete', help="Delete the certificate")
4891 certDelete.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to delete")
4892 certDelete.add_argument('service', choices=['https', 'ldap'], help="Service to delete the certificate")
4893 certDelete.set_defaults(func=certificateDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004894
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05004895 certReplace = certMgmt_subproc.add_parser('replace',
4896 help="Replace the certificate")
4897 certReplace.add_argument('type', choices=['server', 'client', 'authority'],
4898 help="certificate type to replace")
4899 certReplace.add_argument('service', choices=['https', 'ldap'],
4900 help="Service to replace the certificate")
4901 certReplace.add_argument('-f', '--fileloc', required=True,
4902 help="The absolute path to the certificate file")
4903 certReplace.set_defaults(func=certificateReplace)
4904
Marri Devender Rao34646402019-07-01 05:46:03 -05004905 certDisplay = certMgmt_subproc.add_parser('display',
4906 help="Print the certificate")
4907 certDisplay.add_argument('type', choices=['server', 'client', 'authority'],
4908 help="certificate type to display")
4909 certDisplay.set_defaults(func=certificateDisplay)
4910
Marri Devender Raoa208ff82019-07-01 05:51:27 -05004911 certList = certMgmt_subproc.add_parser('list',
4912 help="Certificate list")
4913 certList.set_defaults(func=certificateList)
4914
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004915 certGenerateCSR = certMgmt_subproc.add_parser('generatecsr', help="Generate CSR")
4916 certGenerateCSR.add_argument('type', choices=['server', 'client', 'authority'],
4917 help="Generate CSR")
4918 certGenerateCSR.add_argument('city',
4919 help="The city or locality of the organization making the request")
4920 certGenerateCSR.add_argument('commonName',
4921 help="The fully qualified domain name of the component that is being secured.")
4922 certGenerateCSR.add_argument('country',
4923 help="The country of the organization making the request")
4924 certGenerateCSR.add_argument('organization',
4925 help="The name of the organization making the request.")
4926 certGenerateCSR.add_argument('organizationUnit',
4927 help="The name of the unit or division of the organization making the request.")
4928 certGenerateCSR.add_argument('state',
4929 help="The state, province, or region of the organization making the request.")
4930 certGenerateCSR.add_argument('keyPairAlgorithm', choices=['RSA', 'EC'],
4931 help="The type of key pair for use with signing algorithms.")
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004932 certGenerateCSR.add_argument('keyCurveId',
4933 help="The curve ID to be used with the key, if needed based on the value of the 'KeyPairAlgorithm' parameter.")
4934 certGenerateCSR.add_argument('contactPerson',
4935 help="The name of the user making the request")
4936 certGenerateCSR.add_argument('email',
4937 help="The email address of the contact within the organization")
4938 certGenerateCSR.add_argument('alternativeNames',
4939 help="Additional hostnames of the component that is being secured")
4940 certGenerateCSR.add_argument('givenname',
4941 help="The given name of the user making the request")
4942 certGenerateCSR.add_argument('surname',
4943 help="The surname of the user making the request")
4944 certGenerateCSR.add_argument('unstructuredname',
4945 help="he unstructured name of the subject")
4946 certGenerateCSR.add_argument('initials',
4947 help="The initials of the user making the request")
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004948 certGenerateCSR.set_defaults(func=certificateGenerateCSR)
4949
Matt Spinler7d426c22018-09-24 14:42:07 -05004950 # local users
4951 parser_users = subparsers.add_parser("local_users", help="Work with local users")
4952 parser_users.add_argument('local_users', choices=['disableall','enableall', 'queryenabled'], help="Disable, enable or query local user accounts")
4953 parser_users.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4954 parser_users.set_defaults(func=localUsers)
4955
Ratan Gupta9166cd22018-10-01 18:09:40 +05304956 #LDAP
4957 parser_ldap = subparsers.add_parser("ldap", help="LDAP controls")
4958 ldap_sub = parser_ldap.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
4959
4960 #configure and enable LDAP
4961 parser_ldap_config = ldap_sub.add_parser("enable", help="Configure and enables the LDAP")
4962 parser_ldap_config.add_argument("-a", "--uri", required=True, help="Set LDAP server URI")
4963 parser_ldap_config.add_argument("-B", "--bindDN", required=True, help="Set the bind DN of the LDAP server")
4964 parser_ldap_config.add_argument("-b", "--baseDN", required=True, help="Set the base DN of the LDAP server")
4965 parser_ldap_config.add_argument("-p", "--bindPassword", required=True, help="Set the bind password of the LDAP server")
4966 parser_ldap_config.add_argument("-S", "--scope", choices=['sub','one', 'base'],
4967 help='Specifies the search scope:subtree, one level or base object.')
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004968 parser_ldap_config.add_argument("-t", "--serverType", required=True, choices=['ActiveDirectory','OpenLDAP'],
Ratan Gupta9166cd22018-10-01 18:09:40 +05304969 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004970 parser_ldap_config.add_argument("-g","--groupAttrName", required=False, default='', help="Group Attribute Name")
4971 parser_ldap_config.add_argument("-u","--userAttrName", required=False, default='', help="User Attribute Name")
4972 parser_ldap_config.set_defaults(func=enableLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05304973
4974 # disable LDAP
4975 parser_disable_ldap = ldap_sub.add_parser("disable", help="disables the LDAP")
4976 parser_disable_ldap.set_defaults(func=disableLDAP)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004977 # view-config
4978 parser_ldap_config = \
4979 ldap_sub.add_parser("view-config", help="prints out a list of all \
4980 LDAPS's configured properties")
4981 parser_ldap_config.set_defaults(func=viewLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05304982
Ratan Guptafeee6372018-10-17 23:25:51 +05304983 #create group privilege mapping
4984 parser_ldap_mapper = ldap_sub.add_parser("privilege-mapper", help="LDAP group privilege controls")
4985 parser_ldap_mapper_sub = parser_ldap_mapper.add_subparsers(title='subcommands', description='valid subcommands',
4986 help="sub-command help", dest='command')
4987
4988 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 -05004989 parser_ldap_mapper_create.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4990 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304991 parser_ldap_mapper_create.add_argument("-g","--groupName",required=True,help="Group Name")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004992 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 +05304993 parser_ldap_mapper_create.set_defaults(func=createPrivilegeMapping)
4994
4995 #list group privilege mapping
4996 parser_ldap_mapper_list = parser_ldap_mapper_sub.add_parser("list",help="List privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004997 parser_ldap_mapper_list.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4998 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304999 parser_ldap_mapper_list.set_defaults(func=listPrivilegeMapping)
5000
5001 #delete group privilege mapping
5002 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("delete",help="Delete privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05005003 parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
5004 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05305005 parser_ldap_mapper_delete.add_argument("-g","--groupName",required=True,help="Group Name")
5006 parser_ldap_mapper_delete.set_defaults(func=deletePrivilegeMapping)
5007
Sivas SRR78835272018-11-27 05:27:19 -06005008 #deleteAll group privilege mapping
5009 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("purge",help="Delete All privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05005010 parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
5011 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Sivas SRR78835272018-11-27 05:27:19 -06005012 parser_ldap_mapper_delete.set_defaults(func=deleteAllPrivilegeMapping)
5013
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06005014 # set local user password
5015 parser_set_password = subparsers.add_parser("set_password",
5016 help="Set password of local user")
5017 parser_set_password.add_argument( "-p", "--password", required=True,
5018 help="Password of local user")
5019 parser_set_password.set_defaults(func=setPassword)
5020
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005021 # network
5022 parser_nw = subparsers.add_parser("network", help="network controls")
5023 nw_sub = parser_nw.add_subparsers(title='subcommands',
5024 description='valid subcommands',
5025 help="sub-command help",
5026 dest='command')
5027
5028 # enable DHCP
5029 parser_enable_dhcp = nw_sub.add_parser("enableDHCP",
5030 help="enables the DHCP on given "
5031 "Interface")
5032 parser_enable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005033 help="Name of the ethernet interface(it can"
5034 "be obtained by the "
5035 "command:network view-config)"
5036 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005037 parser_enable_dhcp.set_defaults(func=enableDHCP)
5038
5039 # disable DHCP
5040 parser_disable_dhcp = nw_sub.add_parser("disableDHCP",
5041 help="disables the DHCP on given "
5042 "Interface")
5043 parser_disable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005044 help="Name of the ethernet interface(it can"
5045 "be obtained by the "
5046 "command:network view-config)"
5047 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005048 parser_disable_dhcp.set_defaults(func=disableDHCP)
5049
5050 # get HostName
5051 parser_gethostname = nw_sub.add_parser("getHostName",
5052 help="prints out HostName")
5053 parser_gethostname.set_defaults(func=getHostname)
5054
5055 # set HostName
5056 parser_sethostname = nw_sub.add_parser("setHostName", help="sets HostName")
5057 parser_sethostname.add_argument("-H", "--HostName", required=True,
5058 help="A HostName for the BMC")
5059 parser_sethostname.set_defaults(func=setHostname)
5060
5061 # get domainname
5062 parser_getdomainname = nw_sub.add_parser("getDomainName",
5063 help="prints out DomainName of "
5064 "given Interface")
5065 parser_getdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005066 help="Name of the ethernet interface(it "
5067 "can be obtained by the "
5068 "command:network view-config)"
5069 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005070 parser_getdomainname.set_defaults(func=getDomainName)
5071
5072 # set domainname
5073 parser_setdomainname = nw_sub.add_parser("setDomainName",
5074 help="sets DomainName of given "
5075 "Interface")
5076 parser_setdomainname.add_argument("-D", "--DomainName", required=True,
5077 help="Ex: DomainName=Domain1,Domain2,...")
5078 parser_setdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005079 help="Name of the ethernet interface(it "
5080 "can be obtained by the "
5081 "command:network view-config)"
5082 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005083 parser_setdomainname.set_defaults(func=setDomainName)
5084
5085 # get MACAddress
5086 parser_getmacaddress = nw_sub.add_parser("getMACAddress",
5087 help="prints out MACAddress the "
5088 "given Interface")
5089 parser_getmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005090 help="Name of the ethernet interface(it "
5091 "can be obtained by the "
5092 "command:network view-config)"
5093 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005094 parser_getmacaddress.set_defaults(func=getMACAddress)
5095
5096 # set MACAddress
5097 parser_setmacaddress = nw_sub.add_parser("setMACAddress",
5098 help="sets MACAddress")
5099 parser_setmacaddress.add_argument("-MA", "--MACAddress", required=True,
5100 help="A MACAddress for the given "
5101 "Interface")
5102 parser_setmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005103 help="Name of the ethernet interface(it can"
5104 "be obtained by the "
5105 "command:network view-config)"
5106 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005107 parser_setmacaddress.set_defaults(func=setMACAddress)
5108
5109 # get DefaultGW
5110 parser_getdefaultgw = nw_sub.add_parser("getDefaultGW",
5111 help="prints out DefaultGateway "
5112 "the BMC")
5113 parser_getdefaultgw.set_defaults(func=getDefaultGateway)
5114
5115 # set DefaultGW
5116 parser_setdefaultgw = nw_sub.add_parser("setDefaultGW",
5117 help="sets DefaultGW")
5118 parser_setdefaultgw.add_argument("-GW", "--DefaultGW", required=True,
5119 help="A DefaultGateway for the BMC")
5120 parser_setdefaultgw.set_defaults(func=setDefaultGateway)
5121
5122 # view network Config
5123 parser_ldap_config = nw_sub.add_parser("view-config", help="prints out a "
5124 "list of all network's configured "
5125 "properties")
5126 parser_ldap_config.set_defaults(func=viewNWConfig)
5127
5128 # get DNS
5129 parser_getDNS = nw_sub.add_parser("getDNS",
5130 help="prints out DNS servers on the "
5131 "given interface")
5132 parser_getDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005133 help="Name of the ethernet interface(it can"
5134 "be obtained by the "
5135 "command:network view-config)"
5136 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005137 parser_getDNS.set_defaults(func=getDNS)
5138
5139 # set DNS
5140 parser_setDNS = nw_sub.add_parser("setDNS",
5141 help="sets DNS servers on the given "
5142 "interface")
5143 parser_setDNS.add_argument("-d", "--DNSServers", required=True,
5144 help="Ex: DNSSERVERS=DNS1,DNS2,...")
5145 parser_setDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005146 help="Name of the ethernet interface(it can"
5147 "be obtained by the "
5148 "command:network view-config)"
5149 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005150 parser_setDNS.set_defaults(func=setDNS)
5151
5152 # get NTP
5153 parser_getNTP = nw_sub.add_parser("getNTP",
5154 help="prints out NTP servers on the "
5155 "given interface")
5156 parser_getNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005157 help="Name of the ethernet interface(it can"
5158 "be obtained by the "
5159 "command:network view-config)"
5160 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005161 parser_getNTP.set_defaults(func=getNTP)
5162
5163 # set NTP
5164 parser_setNTP = nw_sub.add_parser("setNTP",
5165 help="sets NTP servers on the given "
5166 "interface")
5167 parser_setNTP.add_argument("-N", "--NTPServers", required=True,
5168 help="Ex: NTPSERVERS=NTP1,NTP2,...")
5169 parser_setNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005170 help="Name of the ethernet interface(it can"
5171 "be obtained by the "
5172 "command:network view-config)"
5173 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005174 parser_setNTP.set_defaults(func=setNTP)
5175
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005176 # configure IP
5177 parser_ip_config = nw_sub.add_parser("addIP", help="Sets IP address to"
5178 "given interface")
5179 parser_ip_config.add_argument("-a", "--address", required=True,
5180 help="IP address of given interface")
5181 parser_ip_config.add_argument("-gw", "--gateway", required=False, default='',
5182 help="The gateway for given interface")
5183 parser_ip_config.add_argument("-l", "--prefixLength", required=True,
5184 help="The prefixLength of IP address")
Sunitha Harish0baf6372019-07-31 03:59:03 -05005185 parser_ip_config.add_argument("-p", "--type", required=True,
5186 choices=['ipv4', 'ipv6'],
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005187 help="The protocol type of the given"
5188 "IP address")
5189 parser_ip_config.add_argument("-I", "--Interface", required=True,
5190 help="Name of the ethernet interface(it can"
5191 "be obtained by the "
5192 "command:network view-config)"
5193 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5194 parser_ip_config.set_defaults(func=addIP)
5195
5196 # getIP
5197 parser_getIP = nw_sub.add_parser("getIP", help="prints out IP address"
5198 "of given interface")
5199 parser_getIP.add_argument("-I", "--Interface", required=True,
5200 help="Name of the ethernet interface(it can"
5201 "be obtained by the command:network view-config)"
5202 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5203 parser_getIP.set_defaults(func=getIP)
5204
5205 # rmIP
5206 parser_rmIP = nw_sub.add_parser("rmIP", help="deletes IP address"
5207 "of given interface")
5208 parser_rmIP.add_argument("-a", "--address", required=True,
5209 help="IP address to remove form given Interface")
5210 parser_rmIP.add_argument("-I", "--Interface", required=True,
5211 help="Name of the ethernet interface(it can"
5212 "be obtained by the command:network view-config)"
5213 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5214 parser_rmIP.set_defaults(func=deleteIP)
5215
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06005216 # add VLAN
5217 parser_create_vlan = nw_sub.add_parser("addVLAN", help="enables VLAN "
5218 "on given interface with given "
5219 "VLAN Identifier")
5220 parser_create_vlan.add_argument("-I", "--Interface", required=True,
5221 choices=['eth0', 'eth1'],
5222 help="Name of the ethernet interface")
5223 parser_create_vlan.add_argument("-n", "--Identifier", required=True,
5224 help="VLAN Identifier")
5225 parser_create_vlan.set_defaults(func=addVLAN)
5226
5227 # delete VLAN
5228 parser_delete_vlan = nw_sub.add_parser("deleteVLAN", help="disables VLAN "
5229 "on given interface with given "
5230 "VLAN Identifier")
5231 parser_delete_vlan.add_argument("-I", "--Interface", required=True,
5232 help="Name of the ethernet interface(it can"
5233 "be obtained by the "
5234 "command:network view-config)"
5235 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5236 parser_delete_vlan.set_defaults(func=deleteVLAN)
5237
5238 # viewDHCPConfig
5239 parser_viewDHCPConfig = nw_sub.add_parser("viewDHCPConfig",
5240 help="Shows DHCP configured "
5241 "Properties")
5242 parser_viewDHCPConfig.set_defaults(func=viewDHCPConfig)
5243
5244 # configureDHCP
5245 parser_configDHCP = nw_sub.add_parser("configureDHCP",
5246 help="Configures/updates DHCP "
5247 "Properties")
5248 parser_configDHCP.add_argument("-d", "--DNSEnabled", type=str2bool,
5249 required=True, help="Sets DNSEnabled property")
5250 parser_configDHCP.add_argument("-n", "--HostNameEnabled", type=str2bool,
5251 required=True,
5252 help="Sets HostNameEnabled property")
5253 parser_configDHCP.add_argument("-t", "--NTPEnabled", type=str2bool,
5254 required=True,
5255 help="Sets NTPEnabled property")
5256 parser_configDHCP.add_argument("-s", "--SendHostNameEnabled", type=str2bool,
5257 required=True,
5258 help="Sets SendHostNameEnabled property")
5259 parser_configDHCP.set_defaults(func=configureDHCP)
5260
5261 # network factory reset
5262 parser_nw_reset = nw_sub.add_parser("nwReset",
5263 help="Resets networks setting to "
5264 "factory defaults. "
5265 "note:Reset settings will be applied "
5266 "after BMC reboot")
5267 parser_nw_reset.set_defaults(func=nwReset)
5268
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005269 return parser
5270
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005271def main(argv=None):
Justin Thalere412dc22018-01-12 16:28:24 -06005272 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005273 main function for running the command line utility as a sub application
5274 """
5275 global toolVersion
Justin Thalerc42e4e52020-05-13 12:04:24 -05005276 toolVersion = "1.19"
Sunitha Harishc99faba2019-07-19 06:55:22 -05005277 global isRedfishSupport
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05005278
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005279 parser = createCommandParser()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005280 args = parser.parse_args(argv)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005281
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005282 totTimeStart = int(round(time.time()*1000))
5283
5284 if(sys.version_info < (3,0)):
5285 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
5286 if sys.version_info >= (3,0):
5287 requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Justin Thalere412dc22018-01-12 16:28:24 -06005288 if (args.version):
Justin Thaler22b1bb52018-03-15 13:31:32 -05005289 print("Version: "+ toolVersion)
Justin Thalere412dc22018-01-12 16:28:24 -06005290 sys.exit(0)
5291 if (hasattr(args, 'fileloc') and args.fileloc is not None and 'print' in args.command):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005292 mysess = None
Justin Thalere412dc22018-01-12 16:28:24 -06005293 print(selPrint('N/A', args, mysess))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005294 else:
Justin Thalere412dc22018-01-12 16:28:24 -06005295 if(hasattr(args, 'host') and hasattr(args,'user')):
5296 if (args.askpw):
5297 pw = getpass.getpass()
5298 elif(args.PW is not None):
5299 pw = args.PW
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05005300 elif(args.PWenvvar):
5301 pw = os.environ['OPENBMCTOOL_PASSWORD']
Justin Thalere412dc22018-01-12 16:28:24 -06005302 else:
5303 print("You must specify a password")
5304 sys.exit()
5305 logintimeStart = int(round(time.time()*1000))
Joy Onyerikwu182c3a32019-10-15 08:33:59 -05005306 mysess = login(args.host, args.user, pw, args.json,
5307 args.command == 'set_password')
Sunitha Harish336cda22019-07-23 02:02:52 -05005308 if(mysess == None):
5309 print("Login Failed!")
5310 sys.exit()
Justin Thalera9415b42018-05-25 19:40:13 -05005311 if(sys.version_info < (3,0)):
5312 if isinstance(mysess, basestring):
5313 print(mysess)
5314 sys.exit(1)
5315 elif sys.version_info >= (3,0):
5316 if isinstance(mysess, str):
5317 print(mysess)
5318 sys.exit(1)
Justin Thalere412dc22018-01-12 16:28:24 -06005319 logintimeStop = int(round(time.time()*1000))
Sunitha Harishc99faba2019-07-19 06:55:22 -05005320 isRedfishSupport = redfishSupportPresent(args.host,mysess)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005321 commandTimeStart = int(round(time.time()*1000))
Justin Thalere412dc22018-01-12 16:28:24 -06005322 output = args.func(args.host, args, mysess)
5323 commandTimeStop = int(round(time.time()*1000))
Justin Thaler761484a2019-03-26 19:20:23 -05005324 if isinstance(output, dict):
5325 print(json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
5326 else:
5327 print(output)
Justin Thalere412dc22018-01-12 16:28:24 -06005328 if (mysess is not None):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005329 logout(args.host, args.user, pw, mysess, args.json)
5330 if(args.procTime):
Justin Thalere412dc22018-01-12 16:28:24 -06005331 print("Total time: " + str(int(round(time.time()*1000))- totTimeStart))
5332 print("loginTime: " + str(logintimeStop - logintimeStart))
5333 print("command Time: " + str(commandTimeStop - commandTimeStart))
5334 else:
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05005335 print("usage:\n"
5336 " OPENBMCTOOL_PASSWORD=secret # if using -E\n"
5337 " openbmctool.py [-h] -H HOST -U USER {-A | -P PW | -E} [-j]\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06005338 "\t[-t POLICYTABLELOC] [-V]\n" +
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05005339 "\t{fru,sensors,sel,chassis,collect_service_data, \
5340 health_check,dump,bmc,mc,gardclear,firmware,logging}\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06005341 "\t...\n" +
5342 "openbmctool.py: error: the following arguments are required: -H/--host, -U/--user")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005343 sys.exit()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005344
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005345if __name__ == '__main__':
Justin Thalere412dc22018-01-12 16:28:24 -06005346 """
5347 main function when called from the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005348
5349 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005350 import sys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005351
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005352 isTTY = sys.stdout.isatty()
5353 assert sys.version_info >= (2,7)
5354 main()