blob: 2710ba3bbdcd90d99a93afe4a0fbf02ff80cadc3 [file] [log] [blame]
Justin Thalerb8807ce2018-05-25 19:16:20 -05001#!/usr/bin/python3
Justin Thalere412dc22018-01-12 16:28:24 -06002"""
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05003 Copyright 2017,2019 IBM Corporation
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004
Justin Thalere412dc22018-01-12 16:28:24 -06005 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16"""
Justin Thalerf9aee3e2017-12-05 12:11:09 -060017import argparse
18import requests
Alvin Wangbf99c582019-10-29 16:40:05 +080019import simplejson
Justin Thalerf9aee3e2017-12-05 12:11:09 -060020import getpass
21import json
22import os
23import urllib3
24import time, datetime
Justin Thalerf9aee3e2017-12-05 12:11:09 -060025import binascii
26import subprocess
27import platform
28import zipfile
Justin Thaler22b1bb52018-03-15 13:31:32 -050029import tarfile
30import tempfile
31import hashlib
Justin Thalera6b5df72018-07-16 11:10:07 -050032import re
Justin Thaler24d4efa2018-11-08 22:48:10 -060033import uuid
Ravi Tejad8be0b42020-03-18 14:31:46 -050034import ssl
35import socket
36import select
37import http.client
38from subprocess import check_output
Justin Thalerf9aee3e2017-12-05 12:11:09 -060039
Ravi Tejad8be0b42020-03-18 14:31:46 -050040
41MAX_NBD_PACKET_SIZE = 131088
Matt Spinler220c3c42019-01-04 15:09:29 -060042jsonHeader = {'Content-Type' : 'application/json'}
43xAuthHeader = {}
Justin Thaler27197622019-01-23 14:42:11 -060044baseTimeout = 60
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -050045serverTypeMap = {
46 'ActiveDirectory' : 'active_directory',
47 'OpenLDAP' : 'openldap'
48 }
Matt Spinler220c3c42019-01-04 15:09:29 -060049
Ravi Tejad8be0b42020-03-18 14:31:46 -050050class NBDPipe:
51
52 def openHTTPSocket(self,args):
53
54 try:
55 _create_unverified_https_context = ssl._create_unverified_context
56 except AttributeError:
57 # Legacy Python that doesn't verify HTTPS certificates by default
58 pass
59 else:
60 # Handle target environment that doesn't support HTTPS verification
61 ssl._create_default_https_context = _create_unverified_https_context
62
63
64 token = gettoken(args)
65 self.conn = http.client.HTTPSConnection(args.host,port=443)
66 URI = "/redfish/v1/Systems/system/LogServices/SystemDump/Entries/"+str(args.dumpNum)+"/Actions/Oem/OpenBmc/LogEntry.DownloadLog"
67 self.conn.request("POST",URI, headers={"X-Auth-Token":token})
68
69 def openTCPSocket(self):
70 # Create a TCP/IP socket
71 self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
72 # Connect the socket to the port where the server is listening
73 server_address = ('localhost', 1043)
74 self.tcp.connect(server_address)
75
76 def waitformessage(self):
77 inputs = [self.conn.sock,self.tcp]
78 outputs = []
79 message_queues = {}
80 while True:
81 readable, writable, exceptional = select.select(
82 inputs, outputs, inputs)
83
84 for s in readable:
85 if s is self.conn.sock:
86
87 data = self.conn.sock.recv(MAX_NBD_PACKET_SIZE)
88 print("<<HTTP")
89 #print(len(data))
90 if data:
91 self.tcp.send(data)
92 else:
93 print ("BMC Closed the connection")
94 self.conn.close()
95 self.tcp.close()
96 sys.exit(1)
97 elif s is self.tcp:
98 data = self.tcp.recv(MAX_NBD_PACKET_SIZE)
99 print(">>TCP")
100 #print(len(data));
101 if data:
102 self.conn.sock.send(data)
103 else:
104 print("NBD server closed the connection")
105 self.conn.sock.close()
106 self.tcp.close()
107 sys.exit(1)
108 for s in exceptional:
109 inputs.remove(s)
110 print("Exceptional closing the socket")
111 s.close()
112
113def getsize(host,args,session):
114 url = "https://"+host+"/redfish/v1/Systems/system/LogServices/SystemDump/Entries/"+str(args.dumpNum)
115 print(url)
116 try:
117 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
118 if resp.status_code==200:
119 size = resp.json()["Oem"]["OpenBmc"]['SizeInB']
120 print(size)
121 return size
122 else:
123 return "Failed get Size"
124 except(requests.exceptions.Timeout):
125 return connectionErrHandler(args.json, "Timeout", None)
126
127 except(requests.exceptions.ConnectionError) as err:
128 return connectionErrHandler(args.json, "ConnectionError", err)
129
130def gettoken(args):
131 mysess = requests.session()
132 resp = mysess.post('https://'+args.host+'/login', headers=jsonHeader,json={"data":[args.user,args.PW]},verify=False)
133 if resp.status_code == 200:
134 cookie = resp.headers['Set-Cookie']
135 match = re.search('SESSION=(\w+);', cookie)
136 return match.group(1)
137
138
139
140def get_pid(name):
141 try:
142 pid = map(int, check_output(["pidof", "-s",name]))
143 except Exception:
144 pid = 0
145
146 return pid
147
148def findThisProcess( process_name ):
149 ps = subprocess.Popen("ps -eaf | grep "+process_name, shell=True, stdout=subprocess.PIPE)
150 output = ps.stdout.read()
151 ps.stdout.close()
152 ps.wait()
153 pid = get_pid(process_name)
154 print(pid)
155 return output
156
157def isThisProcessRunning( process_name ):
158 pid = get_pid(process_name)
159 if (pid == 0 ):
160 return False
161 else:
162 return True
163
164def NBDSetup(host,args,session):
165 user=os.getenv("SUDO_USER")
166 if user is None:
167 path = os.getcwd()
168 nbdServerPath = path + "/nbd-server"
169 print(nbdServerPath,os.path.exists(nbdServerPath))
170 if not os.path.exists(nbdServerPath):
171 print("Error: this program did not run as sudo!\nplease copy nbd-server to current directory and run script again")
172 exit()
173
174 if isThisProcessRunning('nbd-server') == True:
175 print("nbd-server already Running! killing the nbd-server")
176 os.system('killall nbd-server')
177
178 if (args.dumpSaveLoc is not None):
179 if(os.path.exists(args.dumpSaveLoc)):
180 print("Error: File already exists.")
181 exit()
182
183 fp= open(args.dumpSaveLoc,"w")
184 sizeInBytes = getsize(host,args,session)
185 #Round off size to mutiples of 1024
186 size = int(sizeInBytes)
187 print(size)
188 mod = size % 1024
189 if mod :
190 roundoff = 1024 - mod
191 size = size + roundoff
192
193 cmd = 'chmod 777 ' + args.dumpSaveLoc
194 os.system(cmd)
195
196 #Run truncate to create file with given size
197 cmd = 'truncate -s ' + str(size) + ' '+ args.dumpSaveLoc
198 os.system(cmd)
199
200 if user is None:
201 cmd = './nbd-server 1043 '+ args.dumpSaveLoc
202 else:
203 cmd = 'nbd-server 1043 '+ args.dumpSaveLoc
204 os.system(cmd)
205
206
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600207def hilight(textToColor, color, bold):
Justin Thalere412dc22018-01-12 16:28:24 -0600208 """
209 Used to add highlights to various text for displaying in a terminal
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600210
Justin Thalere412dc22018-01-12 16:28:24 -0600211 @param textToColor: string, the text to be colored
212 @param color: string, used to color the text red or green
213 @param bold: boolean, used to bold the textToColor
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600214 @return: Buffered reader containing the modified string.
215 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600216 if(sys.platform.__contains__("win")):
217 if(color == "red"):
218 os.system('color 04')
219 elif(color == "green"):
220 os.system('color 02')
221 else:
222 os.system('color') #reset to default
223 return textToColor
224 else:
225 attr = []
226 if(color == "red"):
227 attr.append('31')
228 elif(color == "green"):
229 attr.append('32')
230 else:
231 attr.append('0')
232 if bold:
233 attr.append('1')
234 else:
235 attr.append('0')
236 return '\x1b[%sm%s\x1b[0m' % (';'.join(attr),textToColor)
237
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600238def connectionErrHandler(jsonFormat, errorStr, err):
Justin Thalere412dc22018-01-12 16:28:24 -0600239 """
240 Error handler various connection errors to bmcs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600241
242 @param jsonFormat: boolean, used to output in json format with an error code.
Justin Thalere412dc22018-01-12 16:28:24 -0600243 @param errorStr: string, used to color the text red or green
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600244 @param err: string, the text from the exception
245 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600246 if errorStr == "Timeout":
247 if not jsonFormat:
248 return("FQPSPIN0000M: Connection timed out. Ensure you have network connectivity to the bmc")
249 else:
Justin Thaler115bca72018-05-25 19:29:08 -0500250 conerror = {}
251 conerror['CommonEventID'] = 'FQPSPIN0000M'
252 conerror['sensor']="N/A"
253 conerror['state']="N/A"
254 conerror['additionalDetails'] = "N/A"
255 conerror['Message']="Connection timed out. Ensure you have network connectivity to the BMC"
256 conerror['LengthyDescription'] = "While trying to establish a connection with the specified BMC, the BMC failed to respond in adequate time. Verify the BMC is functioning properly, and the network connectivity to the BMC is stable."
257 conerror['Serviceable']="Yes"
258 conerror['CallHomeCandidate']= "No"
259 conerror['Severity'] = "Critical"
260 conerror['EventType'] = "Communication Failure/Timeout"
261 conerror['VMMigrationFlag'] = "Yes"
262 conerror["AffectedSubsystem"] = "Interconnect (Networking)"
263 conerror["timestamp"] = str(int(time.time()))
264 conerror["UserAction"] = "Verify network connectivity between the two systems and the bmc is functional."
265 eventdict = {}
266 eventdict['event0'] = conerror
267 eventdict['numAlerts'] = '1'
Justin Thaler115bca72018-05-25 19:29:08 -0500268 errorMessageStr = errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600269 return(errorMessageStr)
270 elif errorStr == "ConnectionError":
271 if not jsonFormat:
272 return("FQPSPIN0001M: " + str(err))
273 else:
Justin Thaler115bca72018-05-25 19:29:08 -0500274 conerror = {}
275 conerror['CommonEventID'] = 'FQPSPIN0001M'
276 conerror['sensor']="N/A"
277 conerror['state']="N/A"
278 conerror['additionalDetails'] = str(err)
279 conerror['Message']="Connection Error. View additional details for more information"
280 conerror['LengthyDescription'] = "A connection error to the specified BMC occurred and additional details are provided. Review these details to resolve the issue."
281 conerror['Serviceable']="Yes"
282 conerror['CallHomeCandidate']= "No"
283 conerror['Severity'] = "Critical"
284 conerror['EventType'] = "Communication Failure/Timeout"
285 conerror['VMMigrationFlag'] = "Yes"
286 conerror["AffectedSubsystem"] = "Interconnect (Networking)"
287 conerror["timestamp"] = str(int(time.time()))
288 conerror["UserAction"] = "Correct the issue highlighted in additional details and try again"
289 eventdict = {}
290 eventdict['event0'] = conerror
291 eventdict['numAlerts'] = '1'
Justin Thaler115bca72018-05-25 19:29:08 -0500292 errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600293 return(errorMessageStr)
Justin Thaler115bca72018-05-25 19:29:08 -0500294
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600295 else:
296 return("Unknown Error: "+ str(err))
297
Justin Thalere412dc22018-01-12 16:28:24 -0600298
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600299def setColWidth(keylist, numCols, dictForOutput, colNames):
Justin Thalere412dc22018-01-12 16:28:24 -0600300 """
301 Sets the output width of the columns to display
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600302
303 @param keylist: list, list of strings representing the keys for the dictForOutput
Justin Thalere412dc22018-01-12 16:28:24 -0600304 @param numcols: the total number of columns in the final output
305 @param dictForOutput: dictionary, contains the information to print to the screen
306 @param colNames: list, The strings to use for the column headings, in order of the keylist
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600307 @return: A list of the column widths for each respective column.
Justin Thalere412dc22018-01-12 16:28:24 -0600308 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600309 colWidths = []
310 for x in range(0, numCols):
311 colWidths.append(0)
312 for key in dictForOutput:
313 for x in range(0, numCols):
314 colWidths[x] = max(colWidths[x], len(str(dictForOutput[key][keylist[x]])))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600315
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600316 for x in range(0, numCols):
317 colWidths[x] = max(colWidths[x], len(colNames[x])) +2
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600318
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600319 return colWidths
320
321def loadPolicyTable(pathToPolicyTable):
Justin Thalere412dc22018-01-12 16:28:24 -0600322 """
323 loads a json based policy table into a dictionary
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600324
Justin Thalere412dc22018-01-12 16:28:24 -0600325 @param value: boolean, the value to convert
326 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600327 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600328 policyTable = {}
329 if(os.path.exists(pathToPolicyTable)):
330 with open(pathToPolicyTable, 'r') as stream:
331 try:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600332 contents =json.load(stream)
333 policyTable = contents['events']
Justin Thalere412dc22018-01-12 16:28:24 -0600334 except Exception as err:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600335 print(err)
336 return policyTable
337
Justin Thalere412dc22018-01-12 16:28:24 -0600338
339def boolToString(value):
340 """
341 converts a boolean value to a human readable string value
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600342
Justin Thalere412dc22018-01-12 16:28:24 -0600343 @param value: boolean, the value to convert
344 @return: A string of "Yes" or "No"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600345 """
Justin Thalere412dc22018-01-12 16:28:24 -0600346 if(value):
347 return "Yes"
348 else:
349 return "No"
350
Justin Thalera6b5df72018-07-16 11:10:07 -0500351def stringToInt(text):
352 """
353 returns an integer if the string can be converted, otherwise returns the string
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600354
Justin Thalera6b5df72018-07-16 11:10:07 -0500355 @param text: the string to try to convert to an integer
356 """
357 if text.isdigit():
358 return int(text)
359 else:
360 return text
Justin Thalere412dc22018-01-12 16:28:24 -0600361
Justin Thalera6b5df72018-07-16 11:10:07 -0500362def naturalSort(text):
363 """
364 provides a way to naturally sort a list
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600365
Justin Thalera6b5df72018-07-16 11:10:07 -0500366 @param text: the key to convert for sorting
367 @return list containing the broken up string parts by integers and strings
368 """
369 stringPartList = []
370 for c in re.split('(\d+)', text):
371 stringPartList.append(stringToInt(c))
372 return stringPartList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600373
Justin Thalere412dc22018-01-12 16:28:24 -0600374def tableDisplay(keylist, colNames, output):
375 """
376 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600377
Justin Thalere412dc22018-01-12 16:28:24 -0600378 @param keylist: list, keys for the output dictionary, ordered by colNames
379 @param colNames: Names for the Table of the columns
380 @param output: The dictionary of data to display
381 @return: Session object
382 """
383 colWidth = setColWidth(keylist, len(colNames), output, colNames)
384 row = ""
385 outputText = ""
386 for i in range(len(colNames)):
387 if (i != 0): row = row + "| "
388 row = row + colNames[i].ljust(colWidth[i])
389 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600390
Justin Thalera6b5df72018-07-16 11:10:07 -0500391 output_keys = list(output.keys())
392 output_keys.sort(key=naturalSort)
393 for key in output_keys:
Justin Thalere412dc22018-01-12 16:28:24 -0600394 row = ""
Justin Thaler8fe0c732018-07-24 14:32:35 -0500395 for i in range(len(keylist)):
Justin Thalere412dc22018-01-12 16:28:24 -0600396 if (i != 0): row = row + "| "
397 row = row + output[key][keylist[i]].ljust(colWidth[i])
398 outputText += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600399
Justin Thalere412dc22018-01-12 16:28:24 -0600400 return outputText
401
Justin Thaler22b1bb52018-03-15 13:31:32 -0500402def checkFWactivation(host, args, session):
403 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600404 Checks the software inventory for an image that is being activated.
405
Justin Thaler22b1bb52018-03-15 13:31:32 -0500406 @return: True if an image is being activated, false is no activations are happening
407 """
408 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thaler22b1bb52018-03-15 13:31:32 -0500409 try:
Justin Thaler27197622019-01-23 14:42:11 -0600410 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -0500411 except(requests.exceptions.Timeout):
412 print(connectionErrHandler(args.json, "Timeout", None))
413 return(True)
414 except(requests.exceptions.ConnectionError) as err:
415 print( connectionErrHandler(args.json, "ConnectionError", err))
416 return True
Justin Thaler3a5771b2019-01-23 14:31:52 -0600417 fwInfo = resp.json()['data']
Justin Thaler22b1bb52018-03-15 13:31:32 -0500418 for key in fwInfo:
419 if 'Activation' in fwInfo[key]:
420 if 'Activating' in fwInfo[key]['Activation'] or 'Activating' in fwInfo[key]['RequestedActivation']:
421 return True
422 return False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600423
Joy Onyerikwu182c3a32019-10-15 08:33:59 -0500424def login(host, username, pw,jsonFormat, allowExpiredPassword):
Justin Thalere412dc22018-01-12 16:28:24 -0600425 """
426 Logs into the BMC and creates a session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600427
Justin Thalere412dc22018-01-12 16:28:24 -0600428 @param host: string, the hostname or IP address of the bmc to log into
429 @param username: The user name for the bmc to log into
430 @param pw: The password for the BMC to log into
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600431 @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true.
Joy Onyerikwu182c3a32019-10-15 08:33:59 -0500432 @param allowExpiredPassword: true, if the requested operation should
433 be allowed when the password is expired
Justin Thalere412dc22018-01-12 16:28:24 -0600434 @return: Session object
435 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600436 if(jsonFormat==False):
437 print("Attempting login...")
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600438 mysess = requests.session()
439 try:
Justin Thaler27197622019-01-23 14:42:11 -0600440 r = mysess.post('https://'+host+'/login', headers=jsonHeader, json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
Sunitha Harish336cda22019-07-23 02:02:52 -0500441 if r.status_code == 200:
442 cookie = r.headers['Set-Cookie']
443 match = re.search('SESSION=(\w+);', cookie)
444 if match:
445 xAuthHeader['X-Auth-Token'] = match.group(1)
446 jsonHeader.update(xAuthHeader)
447 loginMessage = json.loads(r.text)
448 if (loginMessage['status'] != "ok"):
449 print(loginMessage["data"]["description"].encode('utf-8'))
450 sys.exit(1)
Joy Onyerikwu182c3a32019-10-15 08:33:59 -0500451 if (('extendedMessage' in r.json()) and
452 ('The password for this account must be changed' in r.json()['extendedMessage'])):
453 if not allowExpiredPassword:
454 print("The password for this system has expired and must be changed"+
455 "\nsee openbmctool.py set_password --help")
456 logout(host, username, pw, mysess, jsonFormat)
457 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600458# if(sys.version_info < (3,0)):
459# urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
460# if sys.version_info >= (3,0):
461# requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Sunitha Harish336cda22019-07-23 02:02:52 -0500462 return mysess
463 else:
464 return None
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600465 except(requests.exceptions.Timeout):
Justin Thaler115bca72018-05-25 19:29:08 -0500466 return (connectionErrHandler(jsonFormat, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600467 except(requests.exceptions.ConnectionError) as err:
Justin Thaler115bca72018-05-25 19:29:08 -0500468 return (connectionErrHandler(jsonFormat, "ConnectionError", err))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600469
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600470
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600471def logout(host, username, pw, session, jsonFormat):
Justin Thalere412dc22018-01-12 16:28:24 -0600472 """
473 Logs out of the bmc and terminates the session
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600474
Justin Thalere412dc22018-01-12 16:28:24 -0600475 @param host: string, the hostname or IP address of the bmc to log out of
476 @param username: The user name for the bmc to log out of
477 @param pw: The password for the BMC to log out of
478 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600479 @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true.
480 """
Justin Thalere412dc22018-01-12 16:28:24 -0600481 try:
Justin Thaler27197622019-01-23 14:42:11 -0600482 r = session.post('https://'+host+'/logout', headers=jsonHeader,json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600483 except(requests.exceptions.Timeout):
484 print(connectionErrHandler(jsonFormat, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600485
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600486 if(jsonFormat==False):
Matt Spinlereae05b02019-01-24 12:59:34 -0600487 if r.status_code == 200:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600488 print('User ' +username + ' has been logged out')
489
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600490
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600491def fru(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600492 """
493 prints out the system inventory. deprecated see fruPrint and fruList
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600494
Justin Thalere412dc22018-01-12 16:28:24 -0600495 @param host: string, the hostname or IP address of the bmc
496 @param args: contains additional arguments used by the fru sub command
497 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600498 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
499 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600500 #url="https://"+host+"/org/openbmc/inventory/system/chassis/enumerate"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600501
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600502 #print(url)
503 #res = session.get(url, headers=httpHeader, verify=False)
504 #print(res.text)
505 #sample = res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600506
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600507 #inv_list = json.loads(sample)["data"]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600508
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600509 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600510 try:
Justin Thaler27197622019-01-23 14:42:11 -0600511 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600512 except(requests.exceptions.Timeout):
513 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600514
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600515 sample = res.text
516# inv_list.update(json.loads(sample)["data"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600517#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600518# #determine column width's
519# colNames = ["FRU Name", "FRU Type", "Has Fault", "Is FRU", "Present", "Version"]
520# colWidths = setColWidth(["FRU Name", "fru_type", "fault", "is_fru", "present", "version"], 6, inv_list, colNames)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600521#
522# print("FRU Name".ljust(colWidths[0])+ "FRU Type".ljust(colWidths[1]) + "Has Fault".ljust(colWidths[2]) + "Is FRU".ljust(colWidths[3])+
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600523# "Present".ljust(colWidths[4]) + "Version".ljust(colWidths[5]))
524# format the output
525# for key in sorted(inv_list.keys()):
526# keyParts = key.split("/")
527# isFRU = "True" if (inv_list[key]["is_fru"]==1) else "False"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600528#
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600529# fruEntry = (keyParts[len(keyParts) - 1].ljust(colWidths[0]) + inv_list[key]["fru_type"].ljust(colWidths[1])+
530# inv_list[key]["fault"].ljust(colWidths[2])+isFRU.ljust(colWidths[3])+
531# inv_list[key]["present"].ljust(colWidths[4])+ inv_list[key]["version"].ljust(colWidths[5]))
532# if(isTTY):
533# if(inv_list[key]["is_fru"] == 1):
534# color = "green"
535# bold = True
536# else:
537# color='black'
538# bold = False
539# fruEntry = hilight(fruEntry, color, bold)
540# print (fruEntry)
541 return sample
Justin Thalere412dc22018-01-12 16:28:24 -0600542
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600543def fruPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600544 """
545 prints out all inventory
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600546
Justin Thalere412dc22018-01-12 16:28:24 -0600547 @param host: string, the hostname or IP address of the bmc
548 @param args: contains additional arguments used by the fru sub command
549 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600550 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
551 @return returns the total fru list.
552 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600553 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600554 try:
Justin Thaler27197622019-01-23 14:42:11 -0600555 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600556 except(requests.exceptions.Timeout):
557 return(connectionErrHandler(args.json, "Timeout", None))
558
Justin Thaler3a5771b2019-01-23 14:31:52 -0600559 frulist={}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600560# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600561 if res.status_code==200:
562 frulist['Hardware'] = res.json()['data']
563 else:
564 if not args.json:
565 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
566 else:
567 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600568 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600569 try:
Justin Thaler27197622019-01-23 14:42:11 -0600570 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600571 except(requests.exceptions.Timeout):
572 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600573# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600574 if res.status_code==200:
575 frulist['Software'] = res.json()['data']
576 else:
577 if not args.json():
578 return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
579 else:
580 return res.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600581 return frulist
582
Justin Thalere412dc22018-01-12 16:28:24 -0600583
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600584def fruList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600585 """
586 prints out all inventory or only a specific specified item
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600587
Justin Thalere412dc22018-01-12 16:28:24 -0600588 @param host: string, the hostname or IP address of the bmc
589 @param args: contains additional arguments used by the fru sub command
590 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600591 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
592 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600593 if(args.items==True):
594 return fruPrint(host, args, session)
595 else:
Justin Thalere412dc22018-01-12 16:28:24 -0600596 return fruPrint(host, args, session)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600597
598
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600599
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600600def fruStatus(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600601 """
602 prints out the status of all FRUs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600603
Justin Thalere412dc22018-01-12 16:28:24 -0600604 @param host: string, the hostname or IP address of the bmc
605 @param args: contains additional arguments used by the fru sub command
606 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600607 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
608 """
Justin Thalere412dc22018-01-12 16:28:24 -0600609 url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600610 try:
Matt Spinler220c3c42019-01-04 15:09:29 -0600611 res = session.get(url, headers=jsonHeader, verify=False)
Justin Thalere412dc22018-01-12 16:28:24 -0600612 except(requests.exceptions.Timeout):
613 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600614# print(res.text)
Justin Thaler3a5771b2019-01-23 14:31:52 -0600615 frulist = res.json()['data']
Justin Thalere412dc22018-01-12 16:28:24 -0600616 frus = {}
617 for key in frulist:
618 component = frulist[key]
619 isFru = False
620 present = False
621 func = False
622 hasSels = False
623 keyPieces = key.split('/')
624 fruName = keyPieces[-1]
625 if 'core' in fruName: #associate cores to cpus
626 fruName = keyPieces[-2] + '-' + keyPieces[-1]
627 if 'Functional' in component:
628 if('Present' in component):
Justin Thalere412dc22018-01-12 16:28:24 -0600629 if 'FieldReplaceable' in component:
630 if component['FieldReplaceable'] == 1:
631 isFru = True
632 if "fan" in fruName:
633 isFru = True;
634 if component['Present'] == 1:
635 present = True
636 if component['Functional'] == 1:
637 func = True
638 if ((key + "/fault") in frulist):
639 hasSels = True;
640 if args.verbose:
641 if hasSels:
642 loglist = []
643 faults = frulist[key+"/fault"]['endpoints']
644 for item in faults:
645 loglist.append(item.split('/')[-1])
646 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
647 else:
648 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
649 else:
650 frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
Justin Thalerfb9c81c2018-07-16 11:14:37 -0500651 elif "power_supply" in fruName or "powersupply" in fruName:
Justin Thalere412dc22018-01-12 16:28:24 -0600652 if component['Present'] ==1:
653 present = True
654 isFru = True
655 if ((key + "/fault") in frulist):
656 hasSels = True;
657 if args.verbose:
658 if hasSels:
659 loglist = []
660 faults = frulist[key+"/fault"]['endpoints']
Obihörnchenff8035f2018-12-05 21:07:37 +0100661 for item in faults:
662 loglist.append(item.split('/')[-1])
Justin Thalere412dc22018-01-12 16:28:24 -0600663 frus[fruName] = {"compName": fruName, "Functional": "No", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
664 else:
665 frus[fruName] = {"compName": fruName, "Functional": "Yes", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
666 else:
667 frus[fruName] = {"compName": fruName, "Functional": boolToString(not hasSels), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
668 if not args.json:
669 if not args.verbose:
670 colNames = ["Component", "Is a FRU", "Present", "Functional", "Has Logs"]
671 keylist = ["compName", "IsFru", "Present", "Functional", "hasSEL"]
672 else:
673 colNames = ["Component", "Is a FRU", "Present", "Functional", "Assoc. Log Number(s)"]
674 keylist = ["compName", "IsFru", "Present", "Functional", "selList"]
675 return tableDisplay(keylist, colNames, frus)
676 else:
677 return str(json.dumps(frus, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600678
Justin Thalere412dc22018-01-12 16:28:24 -0600679def sensor(host, args, session):
680 """
681 prints out all sensors
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600682
Justin Thalere412dc22018-01-12 16:28:24 -0600683 @param host: string, the hostname or IP address of the bmc
684 @param args: contains additional arguments used by the sensor sub command
685 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600686 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
687 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600688 url="https://"+host+"/xyz/openbmc_project/sensors/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600689 try:
Justin Thaler27197622019-01-23 14:42:11 -0600690 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600691 except(requests.exceptions.Timeout):
692 return(connectionErrHandler(args.json, "Timeout", None))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600693
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600694 #Get OCC status
695 url="https://"+host+"/org/open_power/control/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600696 try:
Justin Thaler27197622019-01-23 14:42:11 -0600697 occres = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600698 except(requests.exceptions.Timeout):
699 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600700 if not args.json:
701 colNames = ['sensor', 'type', 'units', 'value', 'target']
Justin Thaler3a5771b2019-01-23 14:31:52 -0600702 sensors = res.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600703 output = {}
704 for key in sensors:
705 senDict = {}
706 keyparts = key.split("/")
Matt Spinler596ef742019-09-20 08:54:36 -0500707
708 # Associations like the following also show up here:
709 # /xyz/openbmc_project/sensors/<type>/<name>/<assoc-name>
710 # Skip them.
711 # Note: keyparts[0] = '' which is why there are 7 segments.
712 if len(keyparts) > 6:
713 continue
714
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600715 senDict['sensorName'] = keyparts[-1]
716 senDict['type'] = keyparts[-2]
Justin Thalere412dc22018-01-12 16:28:24 -0600717 try:
718 senDict['units'] = sensors[key]['Unit'].split('.')[-1]
719 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500720 senDict['units'] = "N/A"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600721 if('Scale' in sensors[key]):
722 scale = 10 ** sensors[key]['Scale']
723 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600724 scale = 1
Justin Thaler22b1bb52018-03-15 13:31:32 -0500725 try:
726 senDict['value'] = str(sensors[key]['Value'] * scale)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600727 except KeyError:
Justin Thaler22b1bb52018-03-15 13:31:32 -0500728 if 'value' in sensors[key]:
729 senDict['value'] = sensors[key]['value']
730 else:
731 senDict['value'] = "N/A"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600732 if 'Target' in sensors[key]:
733 senDict['target'] = str(sensors[key]['Target'])
734 else:
735 senDict['target'] = 'N/A'
736 output[senDict['sensorName']] = senDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600737
Justin Thaler3a5771b2019-01-23 14:31:52 -0600738 occstatus = occres.json()["data"]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600739 if '/org/open_power/control/occ0' in occstatus:
740 occ0 = occstatus["/org/open_power/control/occ0"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600741 if occ0 == 1:
742 occ0 = 'Active'
743 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600744 occ0 = 'Inactive'
745 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
746 occ1 = occstatus["/org/open_power/control/occ1"]['OccActive']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600747 if occ1 == 1:
748 occ1 = 'Active'
749 else:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600750 occ1 = 'Inactive'
751 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
752 else:
753 output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
754 output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
755 keylist = ['sensorName', 'type', 'units', 'value', 'target']
Justin Thalere412dc22018-01-12 16:28:24 -0600756
757 return tableDisplay(keylist, colNames, output)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600758 else:
759 return res.text + occres.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600760
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600761def sel(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -0600762 """
763 prints out the bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600764
Justin Thalere412dc22018-01-12 16:28:24 -0600765 @param host: string, the hostname or IP address of the bmc
766 @param args: contains additional arguments used by the sel sub command
767 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600768 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
769 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600770
771 url="https://"+host+"/xyz/openbmc_project/logging/entry/enumerate"
Justin Thalere412dc22018-01-12 16:28:24 -0600772 try:
Justin Thaler27197622019-01-23 14:42:11 -0600773 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -0600774 except(requests.exceptions.Timeout):
775 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600776 return res.text
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600777
778
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600779def parseESEL(args, eselRAW):
Justin Thalere412dc22018-01-12 16:28:24 -0600780 """
781 parses the esel data and gets predetermined search terms
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600782
Justin Thalere412dc22018-01-12 16:28:24 -0600783 @param eselRAW: string, the raw esel string from the bmc
784 @return: A dictionary containing the quick snapshot data unless args.fullEsel is listed then a full PEL log is returned
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600785 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600786 eselParts = {}
787 esel_bin = binascii.unhexlify(''.join(eselRAW.split()[16:]))
788 #search terms contains the search term as the key and the return dictionary key as it's value
789 searchTerms = { 'Signature Description':'signatureDescription', 'devdesc':'devdesc',
Justin Thaler22b1bb52018-03-15 13:31:32 -0500790 'Callout type': 'calloutType', 'Procedure':'procedure', 'Sensor Type': 'sensorType'}
Justin Thaler24d4efa2018-11-08 22:48:10 -0600791 uniqueID = str(uuid.uuid4())
792 eselBinPath = tempfile.gettempdir() + os.sep + uniqueID + 'esel.bin'
Justin Thalercf1deae2018-05-25 19:35:21 -0500793 with open(eselBinPath, 'wb') as f:
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600794 f.write(esel_bin)
795 errlPath = ""
796 #use the right errl file for the machine architecture
797 arch = platform.machine()
798 if(arch =='x86_64' or arch =='AMD64'):
799 if os.path.exists('/opt/ibm/ras/bin/x86_64/errl'):
800 errlPath = '/opt/ibm/ras/bin/x86_64/errl'
801 elif os.path.exists('errl/x86_64/errl'):
802 errlPath = 'errl/x86_64/errl'
803 else:
804 errlPath = 'x86_64/errl'
805 elif (platform.machine()=='ppc64le'):
806 if os.path.exists('/opt/ibm/ras/bin/ppc64le/errl'):
807 errlPath = '/opt/ibm/ras/bin/ppc64le/errl'
808 elif os.path.exists('errl/ppc64le/errl'):
809 errlPath = 'errl/ppc64le/errl'
810 else:
811 errlPath = 'ppc64le/errl'
812 else:
813 print("machine architecture not supported for parsing eSELs")
814 return eselParts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600815
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600816 if(os.path.exists(errlPath)):
Justin Thalercf1deae2018-05-25 19:35:21 -0500817 output= subprocess.check_output([errlPath, '-d', '--file='+eselBinPath]).decode('utf-8')
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600818# output = proc.communicate()[0]
819 lines = output.split('\n')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600820
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600821 if(hasattr(args, 'fullEsel')):
822 return output
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600823
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600824 for i in range(0, len(lines)):
825 lineParts = lines[i].split(':')
826 if(len(lineParts)>1): #ignore multi lines, output formatting lines, and other information
827 for term in searchTerms:
828 if(term in lineParts[0]):
829 temp = lines[i][lines[i].find(':')+1:].strip()[:-1].strip()
830 if lines[i+1].find(':') != -1:
831 if (len(lines[i+1].split(':')[0][1:].strip())==0):
832 while(len(lines[i][:lines[i].find(':')].strip())>2):
Justin Thaler43030422018-11-08 22:50:21 -0600833 #has multiple lines, process and update line counter
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600834 if((i+1) <= len(lines)):
835 i+=1
836 else:
837 i=i-1
838 break
Justin Thaler43030422018-11-08 22:50:21 -0600839 #Append the content from the next line removing the pretty display characters
840 #Finds the first colon then starts 2 characters after, then removes all whitespace
841 temp = temp + lines[i][lines[i].find(':')+2:].strip()[:-1].strip()[:-1].strip()
Justin Thaler22b1bb52018-03-15 13:31:32 -0500842 if(searchTerms[term] in eselParts):
843 eselParts[searchTerms[term]] = eselParts[searchTerms[term]] + ", " + temp
844 else:
845 eselParts[searchTerms[term]] = temp
Justin Thalercf1deae2018-05-25 19:35:21 -0500846 os.remove(eselBinPath)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600847 else:
848 print("errl file cannot be found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600849
850 return eselParts
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600851
Justin Thalere412dc22018-01-12 16:28:24 -0600852
Matt Spinler02d0dff2018-08-29 13:19:25 -0500853def getESELSeverity(esel):
854 """
855 Finds the severity type in an eSEL from the User Header section.
856 @param esel - the eSEL data
857 @return severity - e.g. 'Critical'
858 """
859
860 # everything but 1 and 2 are Critical
861 # '1': 'recovered',
862 # '2': 'predictive',
863 # '4': 'unrecoverable',
864 # '5': 'critical',
865 # '6': 'diagnostic',
866 # '7': 'symptom'
867 severities = {
868 '1': 'Informational',
869 '2': 'Warning'
870 }
871
872 try:
873 headerPosition = esel.index('55 48') # 'UH'
874 # The severity is the last byte in the 8 byte section (a byte is ' bb')
875 severity = esel[headerPosition:headerPosition+32].split(' ')[-1]
876 type = severity[0]
877 except ValueError:
878 print("Could not find severity value in UH section in eSEL")
879 type = 'x';
880
881 return severities.get(type, 'Critical')
882
883
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600884def sortSELs(events):
Justin Thalere412dc22018-01-12 16:28:24 -0600885 """
886 sorts the sels by timestamp, then log entry number
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600887
Justin Thalere412dc22018-01-12 16:28:24 -0600888 @param events: Dictionary containing events
889 @return: list containing a list of the ordered log entries, and dictionary of keys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600890 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600891 logNumList = []
892 timestampList = []
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600893 eventKeyDict = {}
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600894 eventsWithTimestamp = {}
895 logNum2events = {}
896 for key in events:
897 if key == 'numAlerts': continue
898 if 'callout' in key: continue
899 timestamp = (events[key]['timestamp'])
900 if timestamp not in timestampList:
901 eventsWithTimestamp[timestamp] = [events[key]['logNum']]
902 else:
903 eventsWithTimestamp[timestamp].append(events[key]['logNum'])
904 #map logNumbers to the event dictionary keys
905 eventKeyDict[str(events[key]['logNum'])] = key
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600906
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600907 timestampList = list(eventsWithTimestamp.keys())
908 timestampList.sort()
909 for ts in timestampList:
910 if len(eventsWithTimestamp[ts]) > 1:
911 tmplist = eventsWithTimestamp[ts]
912 tmplist.sort()
913 logNumList = logNumList + tmplist
914 else:
915 logNumList = logNumList + eventsWithTimestamp[ts]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600916
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600917 return [logNumList, eventKeyDict]
918
Justin Thalere412dc22018-01-12 16:28:24 -0600919
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600920def parseAlerts(policyTable, selEntries, args):
Justin Thalere412dc22018-01-12 16:28:24 -0600921 """
922 parses alerts in the IBM CER format, using an IBM policy Table
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600923
Justin Thalere412dc22018-01-12 16:28:24 -0600924 @param policyTable: dictionary, the policy table entries
925 @param selEntries: dictionary, the alerts retrieved from the bmc
926 @return: A dictionary of the parsed entries, in chronological order
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600927 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600928 eventDict = {}
929 eventNum =""
930 count = 0
931 esel = ""
932 eselParts = {}
933 i2cdevice= ""
Matt Spinler02d0dff2018-08-29 13:19:25 -0500934 eselSeverity = None
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600935
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600936 'prepare and sort the event entries'
937 for key in selEntries:
938 if 'callout' not in key:
939 selEntries[key]['logNum'] = key.split('/')[-1]
940 selEntries[key]['timestamp'] = selEntries[key]['Timestamp']
941 sortedEntries = sortSELs(selEntries)
942 logNumList = sortedEntries[0]
943 eventKeyDict = sortedEntries[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -0600944
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600945 for logNum in logNumList:
946 key = eventKeyDict[logNum]
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600947 hasEsel=False
948 i2creadFail = False
949 if 'callout' in key:
950 continue
951 else:
952 messageID = str(selEntries[key]['Message'])
953 addDataPiece = selEntries[key]['AdditionalData']
954 calloutIndex = 0
955 calloutFound = False
956 for i in range(len(addDataPiece)):
957 if("CALLOUT_INVENTORY_PATH" in addDataPiece[i]):
958 calloutIndex = i
959 calloutFound = True
960 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
961 if("CALLOUT_DEVICE_PATH" in addDataPiece[i]):
962 i2creadFail = True
Matt Spinlerd178a472018-08-31 09:48:52 -0500963
964 fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
965
966 # Fall back to "I2C"/"FSI" if dev path isn't in policy table
967 if (messageID + '||' + fruCallout) not in policyTable:
968 i2cdevice = str(addDataPiece[i]).strip().split('=')[1]
969 i2cdevice = '/'.join(i2cdevice.split('/')[-4:])
970 if 'fsi' in str(addDataPiece[calloutIndex]).split('=')[1]:
971 fruCallout = 'FSI'
972 else:
973 fruCallout = 'I2C'
Justin Thalere34c43a2018-05-25 19:37:55 -0500974 calloutFound = True
975 if("CALLOUT_GPIO_NUM" in addDataPiece[i]):
976 if not calloutFound:
977 fruCallout = 'GPIO'
978 calloutFound = True
979 if("CALLOUT_IIC_BUS" in addDataPiece[i]):
980 if not calloutFound:
981 fruCallout = "I2C"
982 calloutFound = True
983 if("CALLOUT_IPMI_SENSOR_NUM" in addDataPiece[i]):
984 if not calloutFound:
985 fruCallout = "IPMI"
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600986 calloutFound = True
987 if("ESEL" in addDataPiece[i]):
988 esel = str(addDataPiece[i]).strip().split('=')[1]
Matt Spinler02d0dff2018-08-29 13:19:25 -0500989 eselSeverity = getESELSeverity(esel)
Justin Thalerf9aee3e2017-12-05 12:11:09 -0600990 if args.devdebug:
991 eselParts = parseESEL(args, esel)
992 hasEsel=True
993 if("GPU" in addDataPiece[i]):
994 fruCallout = '/xyz/openbmc_project/inventory/system/chassis/motherboard/gpu' + str(addDataPiece[i]).strip()[-1]
995 calloutFound = True
996 if("PROCEDURE" in addDataPiece[i]):
997 fruCallout = str(hex(int(str(addDataPiece[i]).split('=')[1])))[2:]
998 calloutFound = True
Justin Thalere412dc22018-01-12 16:28:24 -0600999 if("RAIL_NAME" in addDataPiece[i]):
1000 calloutFound=True
1001 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
1002 if("INPUT_NAME" in addDataPiece[i]):
1003 calloutFound=True
1004 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
1005 if("SENSOR_TYPE" in addDataPiece[i]):
1006 calloutFound=True
1007 fruCallout = str(addDataPiece[i]).split('=')[1].strip()
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001008
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001009 if(calloutFound):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001010 if fruCallout != "":
1011 policyKey = messageID +"||" + fruCallout
Matt Spinler02d0dff2018-08-29 13:19:25 -05001012
1013 # Also use the severity for hostboot errors
1014 if eselSeverity and messageID == 'org.open_power.Host.Error.Event':
1015 policyKey += '||' + eselSeverity
1016
1017 # if not in the table, fall back to the original key
1018 if policyKey not in policyTable:
1019 policyKey = policyKey.replace('||'+eselSeverity, '')
1020
Justin Thalere34c43a2018-05-25 19:37:55 -05001021 if policyKey not in policyTable:
1022 policyKey = messageID
Justin Thaler22b1bb52018-03-15 13:31:32 -05001023 else:
1024 policyKey = messageID
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001025 else:
1026 policyKey = messageID
1027 event = {}
1028 eventNum = str(count)
1029 if policyKey in policyTable:
1030 for pkey in policyTable[policyKey]:
1031 if(type(policyTable[policyKey][pkey])== bool):
1032 event[pkey] = boolToString(policyTable[policyKey][pkey])
1033 else:
1034 if (i2creadFail and pkey == 'Message'):
1035 event[pkey] = policyTable[policyKey][pkey] + ' ' +i2cdevice
1036 else:
1037 event[pkey] = policyTable[policyKey][pkey]
1038 event['timestamp'] = selEntries[key]['Timestamp']
1039 event['resolved'] = bool(selEntries[key]['Resolved'])
1040 if(hasEsel):
1041 if args.devdebug:
1042 event['eselParts'] = eselParts
1043 event['raweSEL'] = esel
1044 event['logNum'] = key.split('/')[-1]
1045 eventDict['event' + eventNum] = event
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001046
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001047 else:
1048 severity = str(selEntries[key]['Severity']).split('.')[-1]
1049 if severity == 'Error':
1050 severity = 'Critical'
1051 eventDict['event'+eventNum] = {}
1052 eventDict['event' + eventNum]['error'] = "error: Not found in policy table: " + policyKey
1053 eventDict['event' + eventNum]['timestamp'] = selEntries[key]['Timestamp']
1054 eventDict['event' + eventNum]['Severity'] = severity
1055 if(hasEsel):
1056 if args.devdebug:
1057 eventDict['event' +eventNum]['eselParts'] = eselParts
1058 eventDict['event' +eventNum]['raweSEL'] = esel
1059 eventDict['event' +eventNum]['logNum'] = key.split('/')[-1]
1060 eventDict['event' +eventNum]['resolved'] = bool(selEntries[key]['Resolved'])
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001061 count += 1
1062 return eventDict
1063
1064
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001065def selDisplay(events, args):
Justin Thalere412dc22018-01-12 16:28:24 -06001066 """
1067 displays alerts in human readable format
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001068
Justin Thalere412dc22018-01-12 16:28:24 -06001069 @param events: Dictionary containing events
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001070 @return:
1071 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001072 activeAlerts = []
1073 historyAlerts = []
1074 sortedEntries = sortSELs(events)
1075 logNumList = sortedEntries[0]
1076 eventKeyDict = sortedEntries[1]
1077 keylist = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message']
1078 if(args.devdebug):
1079 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message', 'eSEL contents']
1080 keylist.append('eSEL')
1081 else:
1082 colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity', 'Message']
1083 for log in logNumList:
1084 selDict = {}
1085 alert = events[eventKeyDict[str(log)]]
1086 if('error' in alert):
1087 selDict['Entry'] = alert['logNum']
1088 selDict['ID'] = 'Unknown'
1089 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
1090 msg = alert['error']
1091 polMsg = msg.split("policy table:")[0]
1092 msg = msg.split("policy table:")[1]
1093 msgPieces = msg.split("||")
1094 err = msgPieces[0]
1095 if(err.find("org.open_power.")!=-1):
1096 err = err.split("org.open_power.")[1]
1097 elif(err.find("xyz.openbmc_project.")!=-1):
1098 err = err.split("xyz.openbmc_project.")[1]
1099 else:
1100 err = msgPieces[0]
1101 callout = ""
1102 if len(msgPieces) >1:
1103 callout = msgPieces[1]
1104 if(callout.find("/org/open_power/")!=-1):
1105 callout = callout.split("/org/open_power/")[1]
1106 elif(callout.find("/xyz/openbmc_project/")!=-1):
1107 callout = callout.split("/xyz/openbmc_project/")[1]
1108 else:
1109 callout = msgPieces[1]
1110 selDict['Message'] = polMsg +"policy table: "+ err + "||" + callout
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001111 selDict['Serviceable'] = 'Unknown'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001112 selDict['Severity'] = alert['Severity']
1113 else:
1114 selDict['Entry'] = alert['logNum']
1115 selDict['ID'] = alert['CommonEventID']
1116 selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001117 selDict['Message'] = alert['Message']
1118 selDict['Serviceable'] = alert['Serviceable']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001119 selDict['Severity'] = alert['Severity']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001120
1121
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001122 eselOrder = ['refCode','signatureDescription', 'eselType', 'devdesc', 'calloutType', 'procedure']
1123 if ('eselParts' in alert and args.devdebug):
1124 eselOutput = ""
1125 for item in eselOrder:
1126 if item in alert['eselParts']:
1127 eselOutput = eselOutput + item + ": " + alert['eselParts'][item] + " | "
1128 selDict['eSEL'] = eselOutput
1129 else:
1130 if args.devdebug:
1131 selDict['eSEL'] = "None"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001132
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001133 if not alert['resolved']:
1134 activeAlerts.append(selDict)
1135 else:
1136 historyAlerts.append(selDict)
1137 mergedOutput = activeAlerts + historyAlerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001138 colWidth = setColWidth(keylist, len(colNames), dict(enumerate(mergedOutput)), colNames)
1139
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001140 output = ""
1141 if(len(activeAlerts)>0):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001142 row = ""
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001143 output +="----Active Alerts----\n"
1144 for i in range(0, len(colNames)):
1145 if i!=0: row =row + "| "
1146 row = row + colNames[i].ljust(colWidth[i])
1147 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001148
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001149 for i in range(0,len(activeAlerts)):
1150 row = ""
1151 for j in range(len(activeAlerts[i])):
1152 if (j != 0): row = row + "| "
1153 row = row + activeAlerts[i][keylist[j]].ljust(colWidth[j])
1154 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001155
1156 if(len(historyAlerts)>0):
1157 row = ""
1158 output+= "----Historical Alerts----\n"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001159 for i in range(len(colNames)):
1160 if i!=0: row =row + "| "
1161 row = row + colNames[i].ljust(colWidth[i])
1162 output += row + "\n"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001163
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001164 for i in range(0, len(historyAlerts)):
1165 row = ""
1166 for j in range(len(historyAlerts[i])):
1167 if (j != 0): row = row + "| "
1168 row = row + historyAlerts[i][keylist[j]].ljust(colWidth[j])
1169 output += row + "\n"
1170# print(events[eventKeyDict[str(log)]])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001171 return output
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001172
Justin Thalere412dc22018-01-12 16:28:24 -06001173
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001174def selPrint(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001175 """
1176 prints out all bmc alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001177
Justin Thalere412dc22018-01-12 16:28:24 -06001178 @param host: string, the hostname or IP address of the bmc
1179 @param args: contains additional arguments used by the fru sub command
1180 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001181 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1182 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001183 if(args.policyTableLoc is None):
1184 if os.path.exists('policyTable.json'):
1185 ptableLoc = "policyTable.json"
1186 elif os.path.exists('/opt/ibm/ras/lib/policyTable.json'):
1187 ptableLoc = '/opt/ibm/ras/lib/policyTable.json'
1188 else:
1189 ptableLoc = 'lib/policyTable.json'
1190 else:
1191 ptableLoc = args.policyTableLoc
1192 policyTable = loadPolicyTable(ptableLoc)
1193 rawselEntries = ""
1194 if(hasattr(args, 'fileloc') and args.fileloc is not None):
1195 if os.path.exists(args.fileloc):
1196 with open(args.fileloc, 'r') as selFile:
1197 selLines = selFile.readlines()
1198 rawselEntries = ''.join(selLines)
1199 else:
1200 print("Error: File not found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001201 sys.exit(1)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001202 else:
1203 rawselEntries = sel(host, args, session)
1204 loadFailed = False
1205 try:
1206 selEntries = json.loads(rawselEntries)
1207 except ValueError:
1208 loadFailed = True
1209 if loadFailed:
1210 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1211 #need to load json twice as original content was string escaped a second time
1212 selEntries = json.loads(json.loads(cleanSels))
1213 selEntries = selEntries['data']
Justin Thalere412dc22018-01-12 16:28:24 -06001214
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001215 if 'description' in selEntries:
1216 if(args.json):
1217 return("{\n\t\"numAlerts\": 0\n}")
1218 else:
1219 return("No log entries found")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001220
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001221 else:
1222 if(len(policyTable)>0):
1223 events = parseAlerts(policyTable, selEntries, args)
1224 if(args.json):
1225 events["numAlerts"] = len(events)
1226 retValue = str(json.dumps(events, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
1227 return retValue
1228 elif(hasattr(args, 'fullSel')):
1229 return events
1230 else:
1231 #get log numbers to order event entries sequentially
1232 return selDisplay(events, args)
1233 else:
1234 if(args.json):
1235 return selEntries
1236 else:
1237 print("error: Policy Table not found.")
1238 return selEntries
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001239
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001240def selList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001241 """
1242 prints out all all bmc alerts, or only prints out the specified alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001243
Justin Thalere412dc22018-01-12 16:28:24 -06001244 @param host: string, the hostname or IP address of the bmc
1245 @param args: contains additional arguments used by the fru sub command
1246 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001247 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1248 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001249 return(sel(host, args, session))
1250
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001251
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001252def selClear(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001253 """
1254 clears all alerts
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001255
Justin Thalere412dc22018-01-12 16:28:24 -06001256 @param host: string, the hostname or IP address of the bmc
1257 @param args: contains additional arguments used by the fru sub command
1258 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001259 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1260 """
Matt Spinler47b13e92019-01-04 14:58:53 -06001261 url="https://"+host+"/xyz/openbmc_project/logging/action/DeleteAll"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001262 data = "{\"data\": [] }"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001263
Justin Thalere412dc22018-01-12 16:28:24 -06001264 try:
Justin Thaler27197622019-01-23 14:42:11 -06001265 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001266 except(requests.exceptions.Timeout):
1267 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001268 if res.status_code == 200:
1269 return "The Alert Log has been cleared. Please allow a few minutes for the action to complete."
1270 else:
1271 print("Unable to clear the logs, trying to clear 1 at a time")
1272 sels = json.loads(sel(host, args, session))['data']
1273 for key in sels:
1274 if 'callout' not in key:
1275 logNum = key.split('/')[-1]
1276 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
1277 try:
Justin Thaler27197622019-01-23 14:42:11 -06001278 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001279 except(requests.exceptions.Timeout):
1280 return connectionErrHandler(args.json, "Timeout", None)
1281 sys.exit(1)
1282 except(requests.exceptions.ConnectionError) as err:
1283 return connectionErrHandler(args.json, "ConnectionError", err)
1284 sys.exit(1)
1285 return ('Sel clearing complete')
1286
1287def selSetResolved(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001288 """
1289 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001290
Justin Thalere412dc22018-01-12 16:28:24 -06001291 @param host: string, the hostname or IP address of the bmc
1292 @param args: contains additional arguments used by the fru sub command
1293 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001294 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1295 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001296 url="https://"+host+"/xyz/openbmc_project/logging/entry/" + str(args.selNum) + "/attr/Resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001297 data = "{\"data\": 1 }"
Justin Thalere412dc22018-01-12 16:28:24 -06001298 try:
Justin Thaler27197622019-01-23 14:42:11 -06001299 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001300 except(requests.exceptions.Timeout):
1301 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001302 if res.status_code == 200:
1303 return "Sel entry "+ str(args.selNum) +" is now set to resolved"
1304 else:
1305 return "Unable to set the alert to resolved"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001306
Justin Thalere412dc22018-01-12 16:28:24 -06001307def selResolveAll(host, args, session):
1308 """
1309 sets a sel entry to resolved
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001310
Justin Thalere412dc22018-01-12 16:28:24 -06001311 @param host: string, the hostname or IP address of the bmc
1312 @param args: contains additional arguments used by the fru sub command
1313 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001314 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1315 """
Justin Thalere412dc22018-01-12 16:28:24 -06001316 rawselEntries = sel(host, args, session)
1317 loadFailed = False
1318 try:
1319 selEntries = json.loads(rawselEntries)
1320 except ValueError:
1321 loadFailed = True
1322 if loadFailed:
1323 cleanSels = json.dumps(rawselEntries).replace('\\n', '')
1324 #need to load json twice as original content was string escaped a second time
1325 selEntries = json.loads(json.loads(cleanSels))
1326 selEntries = selEntries['data']
1327
1328 if 'description' in selEntries:
1329 if(args.json):
1330 return("{\n\t\"selsResolved\": 0\n}")
1331 else:
1332 return("No log entries found")
1333 else:
1334 d = vars(args)
1335 successlist = []
1336 failedlist = []
1337 for key in selEntries:
1338 if 'callout' not in key:
1339 d['selNum'] = key.split('/')[-1]
1340 resolved = selSetResolved(host,args,session)
1341 if 'Sel entry' in resolved:
1342 successlist.append(d['selNum'])
1343 else:
1344 failedlist.append(d['selNum'])
1345 output = ""
1346 successlist.sort()
1347 failedlist.sort()
1348 if len(successlist)>0:
1349 output = "Successfully resolved: " +', '.join(successlist) +"\n"
1350 if len(failedlist)>0:
1351 output += "Failed to resolve: " + ', '.join(failedlist) + "\n"
1352 return output
1353
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001354def chassisPower(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001355 """
1356 called by the chassis function. Controls the power state of the chassis, or gets the status
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001357
Justin Thalere412dc22018-01-12 16:28:24 -06001358 @param host: string, the hostname or IP address of the bmc
1359 @param args: contains additional arguments used by the fru sub command
1360 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001361 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1362 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001363 if(args.powcmd == 'on'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001364 if checkFWactivation(host, args, session):
1365 return ("Chassis Power control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001366 print("Attempting to Power on...:")
1367 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001368 data = '{"data":"xyz.openbmc_project.State.Host.Transition.On"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001369 try:
Justin Thaler27197622019-01-23 14:42:11 -06001370 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001371 except(requests.exceptions.Timeout):
1372 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001373 return res.text
Justin Thalere412dc22018-01-12 16:28:24 -06001374 elif(args.powcmd == 'softoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001375 if checkFWactivation(host, args, session):
1376 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001377 print("Attempting to Power off gracefully...:")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001378 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001379 data = '{"data":"xyz.openbmc_project.State.Host.Transition.Off"}'
Justin Thalere412dc22018-01-12 16:28:24 -06001380 try:
Justin Thaler27197622019-01-23 14:42:11 -06001381 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001382 except(requests.exceptions.Timeout):
1383 return(connectionErrHandler(args.json, "Timeout", None))
1384 return res.text
1385 elif(args.powcmd == 'hardoff'):
Justin Thaler22b1bb52018-03-15 13:31:32 -05001386 if checkFWactivation(host, args, session):
1387 return ("Chassis Power control disabled during firmware activation")
Justin Thalere412dc22018-01-12 16:28:24 -06001388 print("Attempting to Power off immediately...:")
1389 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06001390 data = '{"data":"xyz.openbmc_project.State.Chassis.Transition.Off"}'
1391 try:
Justin Thaler27197622019-01-23 14:42:11 -06001392 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001393 except(requests.exceptions.Timeout):
1394 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001395 return res.text
1396 elif(args.powcmd == 'status'):
1397 url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState"
Justin Thalere412dc22018-01-12 16:28:24 -06001398 try:
Justin Thaler27197622019-01-23 14:42:11 -06001399 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001400 except(requests.exceptions.Timeout):
1401 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001402 chassisState = json.loads(res.text)['data'].split('.')[-1]
1403 url="https://"+host+"/xyz/openbmc_project/state/host0/attr/CurrentHostState"
Justin Thalere412dc22018-01-12 16:28:24 -06001404 try:
Justin Thaler27197622019-01-23 14:42:11 -06001405 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001406 except(requests.exceptions.Timeout):
1407 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001408 hostState = json.loads(res.text)['data'].split('.')[-1]
1409 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/CurrentBMCState"
Justin Thalere412dc22018-01-12 16:28:24 -06001410 try:
Justin Thaler27197622019-01-23 14:42:11 -06001411 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001412 except(requests.exceptions.Timeout):
1413 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001414 bmcState = json.loads(res.text)['data'].split('.')[-1]
1415 if(args.json):
1416 outDict = {"Chassis Power State" : chassisState, "Host Power State" : hostState, "BMC Power State":bmcState}
1417 return json.dumps(outDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
1418 else:
1419 return "Chassis Power State: " +chassisState + "\nHost Power State: " + hostState + "\nBMC Power State: " + bmcState
1420 else:
1421 return "Invalid chassis power command"
1422
Justin Thalere412dc22018-01-12 16:28:24 -06001423
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001424def chassisIdent(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001425 """
1426 called by the chassis function. Controls the identify led of the chassis. Sets or gets the state
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001427
Justin Thalere412dc22018-01-12 16:28:24 -06001428 @param host: string, the hostname or IP address of the bmc
1429 @param args: contains additional arguments used by the fru sub command
1430 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001431 @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 -06001432 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001433 if(args.identcmd == 'on'):
1434 print("Attempting to turn identify light on...:")
1435 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001436 data = '{"data":true}'
Justin Thalere412dc22018-01-12 16:28:24 -06001437 try:
Justin Thaler27197622019-01-23 14:42:11 -06001438 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001439 except(requests.exceptions.Timeout):
1440 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001441 return res.text
1442 elif(args.identcmd == 'off'):
1443 print("Attempting to turn identify light off...:")
1444 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001445 data = '{"data":false}'
Justin Thalere412dc22018-01-12 16:28:24 -06001446 try:
Justin Thaler27197622019-01-23 14:42:11 -06001447 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001448 except(requests.exceptions.Timeout):
1449 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001450 return res.text
1451 elif(args.identcmd == 'status'):
1452 url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify"
Justin Thalere412dc22018-01-12 16:28:24 -06001453 try:
Justin Thaler27197622019-01-23 14:42:11 -06001454 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06001455 except(requests.exceptions.Timeout):
1456 return(connectionErrHandler(args.json, "Timeout", None))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001457 status = json.loads(res.text)['data']
1458 if(args.json):
1459 return status
1460 else:
1461 if status['Asserted'] == 0:
1462 return "Identify light is off"
1463 else:
1464 return "Identify light is blinking"
1465 else:
1466 return "Invalid chassis identify command"
1467
Justin Thalere412dc22018-01-12 16:28:24 -06001468
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001469def chassis(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001470 """
1471 controls the different chassis commands
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001472
Justin Thalere412dc22018-01-12 16:28:24 -06001473 @param host: string, the hostname or IP address of the bmc
1474 @param args: contains additional arguments used by the fru sub command
1475 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001476 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1477 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001478 if(hasattr(args, 'powcmd')):
1479 result = chassisPower(host,args,session)
1480 elif(hasattr(args, 'identcmd')):
1481 result = chassisIdent(host, args, session)
1482 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05001483 return "This feature is not yet implemented"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001484 return result
Justin Thalere412dc22018-01-12 16:28:24 -06001485
Ravi Tejad8be0b42020-03-18 14:31:46 -05001486def dumpRetrieve(host, args, session):
1487 """
1488 Downloads dump of given dump type
1489
1490 @param host: string, the hostname or IP address of the bmc
1491 @param args: contains additional arguments used by the collectServiceData sub command
1492 @param session: the active session to use
1493 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1494 """
1495 dumpType = args.dumpType
1496 if (args.dumpType=="SystemDump"):
1497 dumpResp=systemDumpRetrieve(host,args,session)
1498 elif(args.dumpType=="bmc"):
1499 dumpResp=bmcDumpRetrieve(host,args,session)
1500 return dumpResp
1501
1502def dumpList(host, args, session):
1503 """
1504 Lists dump of the given dump type
1505
1506 @param host: string, the hostname or IP address of the bmc
1507 @param args: contains additional arguments used by the collectServiceData sub command
1508 @param session: the active session to use
1509 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1510 """
1511 if (args.dumpType=="SystemDump"):
1512 dumpResp=systemDumpList(host,args,session)
1513 elif(args.dumpType=="bmc"):
1514 dumpResp=bmcDumpList(host,args,session)
1515 return dumpResp
1516
1517def dumpDelete(host, args, session):
1518 """
1519 Deletes dump of the given dump type
1520
1521 @param host: string, the hostname or IP address of the bmc
1522 @param args: contains additional arguments used by the collectServiceData sub command
1523 @param session: the active session to use
1524 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1525 """
1526 if (args.dumpType=="SystemDump"):
1527 dumpResp=systemDumpDelete(host,args,session)
1528 elif(args.dumpType=="bmc"):
1529 dumpResp=bmcDumpDelete(host,args,session)
1530 return dumpResp
1531
1532def dumpDeleteAll(host, args, session):
1533 """
1534 Deletes all dumps of the given dump type
1535
1536 @param host: string, the hostname or IP address of the bmc
1537 @param args: contains additional arguments used by the collectServiceData sub command
1538 @param session: the active session to use
1539 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1540 """
1541 if (args.dumpType=="SystemDump"):
1542 dumpResp=systemDumpDeleteAll(host,args,session)
1543 elif(args.dumpType=="bmc"):
1544 dumpResp=bmcDumpDeleteAll(host,args,session)
1545 return dumpResp
1546
1547def dumpCreate(host, args, session):
1548 """
1549 Creates dump for the given dump type
1550
1551 @param host: string, the hostname or IP address of the bmc
1552 @param args: contains additional arguments used by the collectServiceData sub command
1553 @param session: the active session to use
1554 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1555 """
1556 if (args.dumpType=="SystemDump"):
1557 dumpResp=systemDumpCreate(host,args,session)
1558 elif(args.dumpType=="bmc"):
1559 dumpResp=bmcDumpDelete(host,args,session)
1560 return dumpResp
1561
1562
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001563def bmcDumpRetrieve(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001564 """
1565 Downloads a dump file from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001566
Justin Thalere412dc22018-01-12 16:28:24 -06001567 @param host: string, the hostname or IP address of the bmc
1568 @param args: contains additional arguments used by the collectServiceData sub command
1569 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001570 @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 -06001571 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001572 dumpNum = args.dumpNum
1573 if (args.dumpSaveLoc is not None):
1574 saveLoc = args.dumpSaveLoc
1575 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001576 saveLoc = tempfile.gettempdir()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001577 url ='https://'+host+'/download/dump/' + str(dumpNum)
1578 try:
Justin Thaler27197622019-01-23 14:42:11 -06001579 r = session.get(url, headers=jsonHeader, stream=True, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001580 if (args.dumpSaveLoc is not None):
1581 if os.path.exists(saveLoc):
1582 if saveLoc[-1] != os.path.sep:
1583 saveLoc = saveLoc + os.path.sep
1584 filename = saveLoc + host+'-dump' + str(dumpNum) + '.tar.xz'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001585
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001586 else:
1587 return 'Invalid save location specified'
1588 else:
Justin Thalercf1deae2018-05-25 19:35:21 -05001589 filename = tempfile.gettempdir()+os.sep + host+'-dump' + str(dumpNum) + '.tar.xz'
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001590
1591 with open(filename, 'wb') as f:
1592 for chunk in r.iter_content(chunk_size =1024):
1593 if chunk:
1594 f.write(chunk)
1595 return 'Saved as ' + filename
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001596
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001597 except(requests.exceptions.Timeout):
1598 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001599
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001600 except(requests.exceptions.ConnectionError) as err:
1601 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001602
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001603def bmcDumpList(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001604 """
1605 Lists the number of dump files on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001606
Justin Thalere412dc22018-01-12 16:28:24 -06001607 @param host: string, the hostname or IP address of the bmc
1608 @param args: contains additional arguments used by the collectServiceData sub command
1609 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001610 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1611 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001612 url ='https://'+host+'/xyz/openbmc_project/dump/list'
1613 try:
Justin Thaler27197622019-01-23 14:42:11 -06001614 r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3a5771b2019-01-23 14:31:52 -06001615 dumpList = r.json()
1616 return dumpList
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001617 except(requests.exceptions.Timeout):
1618 return connectionErrHandler(args.json, "Timeout", None)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001619
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001620 except(requests.exceptions.ConnectionError) as err:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001621 return connectionErrHandler(args.json, "ConnectionError", err)
1622
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001623def bmcDumpDelete(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001624 """
1625 Deletes BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001626
Justin Thalere412dc22018-01-12 16:28:24 -06001627 @param host: string, the hostname or IP address of the bmc
1628 @param args: contains additional arguments used by the collectServiceData sub command
1629 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001630 @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 -06001631 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001632 dumpList = []
1633 successList = []
1634 failedList = []
1635 if args.dumpNum is not None:
1636 if isinstance(args.dumpNum, list):
1637 dumpList = args.dumpNum
1638 else:
1639 dumpList.append(args.dumpNum)
1640 for dumpNum in dumpList:
1641 url ='https://'+host+'/xyz/openbmc_project/dump/entry/'+str(dumpNum)+'/action/Delete'
1642 try:
Justin Thaler27197622019-01-23 14:42:11 -06001643 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001644 if r.status_code == 200:
1645 successList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001646 else:
1647 failedList.append(str(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001648 except(requests.exceptions.Timeout):
1649 return connectionErrHandler(args.json, "Timeout", None)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001650 except(requests.exceptions.ConnectionError) as err:
1651 return connectionErrHandler(args.json, "ConnectionError", err)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001652 output = "Successfully deleted dumps: " + ', '.join(successList)
1653 if(len(failedList)>0):
1654 output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
1655 return output
1656 else:
1657 return 'You must specify an entry number to delete'
1658
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001659def bmcDumpDeleteAll(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001660 """
1661 Deletes All BMC dump files from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001662
Justin Thalere412dc22018-01-12 16:28:24 -06001663 @param host: string, the hostname or IP address of the bmc
1664 @param args: contains additional arguments used by the collectServiceData sub command
1665 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001666 @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 -06001667 """
1668 dumpResp = bmcDumpList(host, args, session)
1669 if 'FQPSPIN0000M' in dumpResp or 'FQPSPIN0001M'in dumpResp:
1670 return dumpResp
Justin Thaler3a5771b2019-01-23 14:31:52 -06001671 dumpList = dumpResp['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001672 d = vars(args)
1673 dumpNums = []
1674 for dump in dumpList:
Alvin Wang28bd09d2019-10-28 13:23:58 +08001675 dumpNum = dump.strip().split('/')[-1]
1676 if dumpNum.isdigit():
1677 dumpNums.append(int(dumpNum))
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001678 d['dumpNum'] = dumpNums
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001679
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001680 return bmcDumpDelete(host, args, session)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001681
Justin Thalere412dc22018-01-12 16:28:24 -06001682
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001683def bmcDumpCreate(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06001684 """
1685 Creates a bmc dump file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001686
Justin Thalere412dc22018-01-12 16:28:24 -06001687 @param host: string, the hostname or IP address of the bmc
1688 @param args: contains additional arguments used by the collectServiceData sub command
1689 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001690 @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 -06001691 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001692 url = 'https://'+host+'/xyz/openbmc_project/dump/action/CreateDump'
1693 try:
Justin Thaler27197622019-01-23 14:42:11 -06001694 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
Matt Spinlereae05b02019-01-24 12:59:34 -06001695 if(r.status_code == 200 and not args.json):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001696 return ('Dump successfully created')
Justin Thaler3a5771b2019-01-23 14:31:52 -06001697 elif(args.json):
1698 return r.json()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06001699 else:
1700 return ('Failed to create dump')
1701 except(requests.exceptions.Timeout):
1702 return connectionErrHandler(args.json, "Timeout", None)
1703 except(requests.exceptions.ConnectionError) as err:
1704 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001705
Ravi Tejad8be0b42020-03-18 14:31:46 -05001706def systemDumpRetrieve(host, args, session):
1707 """
1708 Downloads system dump
1709
1710 @param host: string, the hostname or IP address of the bmc
1711 @param args: contains additional arguments used by the collectServiceData sub command
1712 @param session: the active session to use
1713 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1714 """
1715 NBDSetup(host,args,session)
1716 pipe = NBDPipe()
1717 pipe.openHTTPSocket(args)
1718 pipe.openTCPSocket()
1719 pipe.waitformessage()
1720
1721def systemDumpList(host, args, session):
1722 """
1723 Lists system dumps
1724
1725 @param host: string, the hostname or IP address of the bmc
1726 @param args: contains additional arguments used by the collectServiceData sub command
1727 @param session: the active session to use
1728 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1729 """
1730 print("in systemDumpList")
1731 url = "https://"+host+"/redfish/v1/Systems/system/LogServices/"+args.dumpType+"/Entries"
1732 try:
1733 r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
1734 dumpList = r.json()
1735 return dumpList
1736 except(requests.exceptions.Timeout):
1737 return connectionErrHandler(args.json, "Timeout", None)
1738
1739 except(requests.exceptions.ConnectionError) as err:
1740 return connectionErrHandler(args.json, "ConnectionError", err)
1741
1742
1743def systemDumpDelete(host, args, session):
1744 """
1745 Deletes system dump
1746
1747 @param host: string, the hostname or IP address of the bmc
1748 @param args: contains additional arguments used by the collectServiceData sub command
1749 @param session: the active session to use
1750 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1751 """
1752 dumpList = []
1753 successList = []
1754 failedList = []
1755 if args.dumpNum is not None:
1756 if isinstance(args.dumpNum, list):
1757 dumpList = args.dumpNum
1758 else:
1759 dumpList.append(args.dumpNum)
1760 for dumpNum in dumpList:
1761 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/'+args.dumpType+'/Entries/'+ str(dumpNum)
1762 try:
1763 r = session.delete(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1764 if r.status_code == 200:
1765 successList.append(str(dumpNum))
1766 else:
1767 failedList.append(str(dumpNum))
1768 except(requests.exceptions.Timeout):
1769 return connectionErrHandler(args.json, "Timeout", None)
1770 except(requests.exceptions.ConnectionError) as err:
1771 return connectionErrHandler(args.json, "ConnectionError", err)
1772 output = "Successfully deleted dumps: " + ', '.join(successList)
1773 if(len(failedList)>0):
1774 output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
1775 return output
1776 else:
1777 return 'You must specify an entry number to delete'
1778
1779def systemDumpDeleteAll(host, args, session):
1780 """
1781 Deletes All system dumps
1782
1783 @param host: string, the hostname or IP address of the bmc
1784 @param args: contains additional arguments used by the collectServiceData sub command
1785 @param session: the active session to use
1786 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1787 """
1788 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/'+args.dumpType+'/Actions/LogService.ClearLog'
1789 try:
1790 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1791 if(r.status_code == 200 and not args.json):
1792 return ('Dumps successfully cleared')
1793 elif(args.json):
1794 return r.json()
1795 else:
1796 return ('Failed to clear dumps')
1797 except(requests.exceptions.Timeout):
1798 return connectionErrHandler(args.json, "Timeout", None)
1799 except(requests.exceptions.ConnectionError) as err:
1800 return connectionErrHandler(args.json, "ConnectionError", err)
1801
1802def systemDumpCreate(host, args, session):
1803 """
1804 Creates a system dump
1805
1806 @param host: string, the hostname or IP address of the bmc
1807 @param args: contains additional arguments used by the collectServiceData sub command
1808 @param session: the active session to use
1809 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1810 """
1811 url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/'+args.dumpType+'/Actions/Oem/Openbmc/LogService.CreateLog'
1812 try:
1813 r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
1814 if(r.status_code == 200 and not args.json):
1815 return ('Dump successfully created')
1816 elif(args.json):
1817 return r.json()
1818 else:
1819 return ('Failed to create dump')
1820 except(requests.exceptions.Timeout):
1821 return connectionErrHandler(args.json, "Timeout", None)
1822 except(requests.exceptions.ConnectionError) as err:
1823 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001824
Justin Thaler666cf342019-01-23 14:44:27 -06001825def csdDumpInitiate(host, args, session):
1826 """
1827 Starts the process of getting the current list of dumps then initiates the creation of one.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06001828
Justin Thaler666cf342019-01-23 14:44:27 -06001829 @param host: string, the hostname or IP address of the bmc
1830 @param args: contains additional arguments used by the collectServiceData sub command
1831 @param session: the active session to use
1832 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1833 """
1834 errorInfo = ""
1835 dumpcount = 0
1836 try:
1837 d = vars(args)
1838 d['json'] = True
1839 except Exception as e:
1840 errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
1841
1842 try:
1843 for i in range(3):
1844 dumpInfo = bmcDumpList(host, args, session)
1845 if 'data' in dumpInfo:
1846 dumpcount = len(dumpInfo['data'])
1847 break
1848 else:
1849 errorInfo+= "Dump List Message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n"
1850 except Exception as e:
1851 errorInfo+= "Failed to collect the list of dumps.\nException: {eInfo}\n".format(eInfo=e)
1852
1853 #Create a user initiated dump
1854 try:
1855 for i in range(3):
1856 dumpcreated = bmcDumpCreate(host, args, session)
1857 if 'message' in dumpcreated:
1858 if 'ok' in dumpcreated['message'].lower():
1859 break
1860 else:
1861 errorInfo+= "Dump create message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n"
1862 else:
1863 errorInfo+= "Dump create message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n"
1864 except Exception as e:
1865 errorInfo+= "Dump create exception encountered: {eInfo}\n".format(eInfo=e)
1866
1867 output = {}
1868 output['errors'] = errorInfo
1869 output['dumpcount'] = dumpcount
1870 return output
1871
1872def csdInventory(host, args,session, fileDir):
1873 """
1874 Collects the BMC inventory, retrying if necessary
1875
1876 @param host: string, the hostname or IP address of the bmc
1877 @param args: contains additional arguments used by the collectServiceData sub command
1878 @param session: the active session to use
1879 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1880 @param fileDir: string representation of the path to use for putting files created
1881 """
1882 errorInfo = "===========Inventory =============\n"
1883 output={}
1884 inventoryCollected = False
1885 try:
1886 for i in range(3):
1887 frulist = fruPrint(host, args, session)
1888 if 'Hardware' in frulist:
1889 inventoryCollected = True
1890 break
1891 else:
1892 errorInfo += json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1893 except Exception as e:
1894 errorInfo += "Inventory collection exception: {eInfo}\n".format(eInfo=e)
1895 if inventoryCollected:
1896 try:
1897 with open(fileDir +os.sep+'inventory.txt', 'w') as f:
1898 f.write(json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
1899 print("Inventory collected and stored in " + fileDir + os.sep + "inventory.txt")
1900 output['fileLoc'] = fileDir+os.sep+'inventory.txt'
1901 except Exception as e:
1902 print("Failed to write inventory to file.")
1903 errorInfo += "Error writing inventory to the file. Exception: {eInfo}\n".format(eInfo=e)
1904
1905 output['errors'] = errorInfo
1906
1907 return output
1908
1909def csdSensors(host, args,session, fileDir):
1910 """
1911 Collects the BMC sensor readings, retrying if necessary
1912
1913 @param host: string, the hostname or IP address of the bmc
1914 @param args: contains additional arguments used by the collectServiceData sub command
1915 @param session: the active session to use
1916 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
1917 @param fileDir: string representation of the path to use for putting files created
1918 """
1919 errorInfo = "===========Sensors =============\n"
1920 sensorsCollected = False
1921 output={}
1922 try:
1923 d = vars(args)
1924 d['json'] = False
1925 except Exception as e:
1926 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
1927
1928 try:
1929 for i in range(3):
1930 sensorReadings = sensor(host, args, session)
1931 if 'OCC0' in sensorReadings:
1932 sensorsCollected = True
1933 break
1934 else:
1935 errorInfo += sensorReadings
1936 except Exception as e:
1937 errorInfo += "Sensor reading collection exception: {eInfo}\n".format(eInfo=e)
1938 if sensorsCollected:
1939 try:
1940 with open(fileDir +os.sep+'sensorReadings.txt', 'w') as f:
1941 f.write(sensorReadings)
1942 print("Sensor readings collected and stored in " + fileDir + os.sep+ "sensorReadings.txt")
1943 output['fileLoc'] = fileDir+os.sep+'sensorReadings.txt'
1944 except Exception as e:
1945 print("Failed to write sensor readings to file system.")
1946 errorInfo += "Error writing sensor readings to the file. Exception: {eInfo}\n".format(eInfo=e)
1947
1948 output['errors'] = errorInfo
1949 return output
1950
1951def csdLEDs(host,args, session, fileDir):
1952 """
1953 Collects the BMC LED status, 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 = "===========LEDs =============\n"
1962 ledsCollected = False
1963 output={}
1964 try:
1965 d = vars(args)
1966 d['json'] = True
1967 except Exception as e:
1968 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
1969 try:
1970 url="https://"+host+"/xyz/openbmc_project/led/enumerate"
1971 httpHeader = {'Content-Type':'application/json'}
1972 for i in range(3):
1973 try:
1974 ledRes = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
1975 if ledRes.status_code == 200:
1976 ledsCollected = True
1977 leds = ledRes.json()['data']
1978 break
1979 else:
1980 errorInfo += ledRes.text
1981 except(requests.exceptions.Timeout):
1982 errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1983 except(requests.exceptions.ConnectionError) as err:
1984 errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
1985 except Exception as e:
1986 errorInfo += "LED status collection exception: {eInfo}\n".format(eInfo=e)
1987
1988 if ledsCollected:
1989 try:
1990 with open(fileDir +os.sep+'ledStatus.txt', 'w') as f:
1991 f.write(json.dumps(leds, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
1992 print("LED status collected and stored in " + fileDir + os.sep+ "ledStatus.txt")
1993 output['fileLoc'] = fileDir+os.sep+'ledStatus.txt'
1994 except Exception as e:
1995 print("Failed to write LED status to file system.")
1996 errorInfo += "Error writing LED status to the file. Exception: {eInfo}\n".format(eInfo=e)
1997
1998 output['errors'] = errorInfo
1999 return output
2000
2001def csdSelShortList(host, args, session, fileDir):
2002 """
2003 Collects the BMC log entries, retrying if necessary
2004
2005 @param host: string, the hostname or IP address of the bmc
2006 @param args: contains additional arguments used by the collectServiceData sub command
2007 @param session: the active session to use
2008 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2009 @param fileDir: string representation of the path to use for putting files created
2010 """
2011 errorInfo = "===========SEL Short List =============\n"
2012 selsCollected = False
2013 output={}
2014 try:
2015 d = vars(args)
2016 d['json'] = False
2017 except Exception as e:
2018 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
2019
2020 try:
2021 for i in range(3):
2022 sels = selPrint(host,args,session)
2023 if '----Active Alerts----' in sels or 'No log entries found' in sels or '----Historical Alerts----' in sels:
2024 selsCollected = True
2025 break
2026 else:
2027 errorInfo += sels + '\n'
2028 except Exception as e:
2029 errorInfo += "SEL short list collection exception: {eInfo}\n".format(eInfo=e)
2030
2031 if selsCollected:
2032 try:
2033 with open(fileDir +os.sep+'SELshortlist.txt', 'w') as f:
2034 f.write(sels)
2035 print("SEL short list collected and stored in " + fileDir + os.sep+ "SELshortlist.txt")
2036 output['fileLoc'] = fileDir+os.sep+'SELshortlist.txt'
2037 except Exception as e:
2038 print("Failed to write SEL short list to file system.")
2039 errorInfo += "Error writing SEL short list to the file. Exception: {eInfo}\n".format(eInfo=e)
2040
2041 output['errors'] = errorInfo
2042 return output
2043
2044def csdParsedSels(host, args, session, fileDir):
2045 """
2046 Collects the BMC log entries, retrying if necessary
2047
2048 @param host: string, the hostname or IP address of the bmc
2049 @param args: contains additional arguments used by the collectServiceData sub command
2050 @param session: the active session to use
2051 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2052 @param fileDir: string representation of the path to use for putting files created
2053 """
2054 errorInfo = "===========SEL Parsed List =============\n"
2055 selsCollected = False
2056 output={}
2057 try:
2058 d = vars(args)
2059 d['json'] = True
2060 d['fullEsel'] = True
2061 except Exception as e:
2062 errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
2063
2064 try:
2065 for i in range(3):
2066 parsedfullsels = json.loads(selPrint(host,args,session))
2067 if 'numAlerts' in parsedfullsels:
2068 selsCollected = True
2069 break
2070 else:
2071 errorInfo += parsedfullsels + '\n'
2072 except Exception as e:
2073 errorInfo += "Parsed full SELs collection exception: {eInfo}\n".format(eInfo=e)
2074
2075 if selsCollected:
2076 try:
2077 sortedSELs = sortSELs(parsedfullsels)
2078 with open(fileDir +os.sep+'parsedSELs.txt', 'w') as f:
2079 for log in sortedSELs[0]:
2080 esel = ""
2081 parsedfullsels[sortedSELs[1][str(log)]]['timestamp'] = datetime.datetime.fromtimestamp(int(parsedfullsels[sortedSELs[1][str(log)]]['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
2082 if ('raweSEL' in parsedfullsels[sortedSELs[1][str(log)]] and args.devdebug):
2083 esel = parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
2084 del parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
2085 f.write(json.dumps(parsedfullsels[sortedSELs[1][str(log)]],sort_keys=True, indent=4, separators=(',', ': ')))
2086 if(args.devdebug and esel != ""):
2087 f.write(parseESEL(args, esel))
2088 print("Parsed SELs collected and stored in " + fileDir + os.sep+ "parsedSELs.txt")
2089 output['fileLoc'] = fileDir+os.sep+'parsedSELs.txt'
2090 except Exception as e:
2091 print("Failed to write fully parsed SELs to file system.")
2092 errorInfo += "Error writing fully parsed SELs to the file. Exception: {eInfo}\n".format(eInfo=e)
2093
2094 output['errors'] = errorInfo
2095 return output
2096
2097def csdFullEnumeration(host, args, session, fileDir):
2098 """
2099 Collects a full enumeration of /xyz/openbmc_project/, retrying if necessary
2100
2101 @param host: string, the hostname or IP address of the bmc
2102 @param args: contains additional arguments used by the collectServiceData sub command
2103 @param session: the active session to use
2104 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2105 @param fileDir: string representation of the path to use for putting files created
2106 """
2107 errorInfo = "===========BMC Full Enumeration =============\n"
2108 bmcFullCollected = False
2109 output={}
2110 try:
2111 d = vars(args)
2112 d['json'] = True
2113 except Exception as e:
2114 errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
2115 try:
2116 print("Attempting to get a full BMC enumeration")
2117 url="https://"+host+"/xyz/openbmc_project/enumerate"
2118 httpHeader = {'Content-Type':'application/json'}
2119 for i in range(3):
2120 try:
2121 bmcRes = session.get(url, headers=jsonHeader, verify=False, timeout=180)
2122 if bmcRes.status_code == 200:
2123 bmcFullCollected = True
2124 fullEnumeration = bmcRes.json()
2125 break
2126 else:
2127 errorInfo += bmcRes.text
2128 except(requests.exceptions.Timeout):
2129 errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
2130 except(requests.exceptions.ConnectionError) as err:
2131 errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
2132 except Exception as e:
2133 errorInfo += "RAW BMC data collection exception: {eInfo}\n".format(eInfo=e)
2134
2135 if bmcFullCollected:
2136 try:
2137 with open(fileDir +os.sep+'bmcFullRaw.txt', 'w') as f:
2138 f.write(json.dumps(fullEnumeration, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
2139 print("RAW BMC data collected and saved into " + fileDir + os.sep+ "bmcFullRaw.txt")
2140 output['fileLoc'] = fileDir+os.sep+'bmcFullRaw.txt'
2141 except Exception as e:
2142 print("Failed to write RAW BMC data to file system.")
2143 errorInfo += "Error writing RAW BMC data collection to the file. Exception: {eInfo}\n".format(eInfo=e)
2144
2145 output['errors'] = errorInfo
2146 return output
2147
2148def csdCollectAllDumps(host, args, session, fileDir):
2149 """
2150 Collects all of the bmc dump files and stores them in fileDir
2151
2152 @param host: string, the hostname or IP address of the bmc
2153 @param args: contains additional arguments used by the collectServiceData sub command
2154 @param session: the active session to use
2155 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2156 @param fileDir: string representation of the path to use for putting files created
2157 """
2158
2159 errorInfo = "===========BMC Dump Collection =============\n"
2160 dumpListCollected = False
2161 output={}
2162 dumpList = {}
2163 try:
2164 d = vars(args)
2165 d['json'] = True
2166 d['dumpSaveLoc'] = fileDir
2167 except Exception as e:
2168 errorInfo += "Failed to set the json flag to True, or failed to set the dumpSave Location \n Exception: {eInfo}\n".format(eInfo=e)
2169
2170 print('Collecting bmc dump files')
2171
2172 try:
2173 for i in range(3):
2174 dumpResp = bmcDumpList(host, args, session)
2175 if 'message' in dumpResp:
2176 if 'ok' in dumpResp['message'].lower():
2177 dumpList = dumpResp['data']
2178 dumpListCollected = True
2179 break
2180 else:
2181 errorInfo += "Status was not OK when retrieving the list of dumps available. \n Response: \n{resp}\n".format(resp=dumpResp)
2182 else:
2183 errorInfo += "Invalid response received from the BMC while retrieving the list of dumps available.\n {resp}\n".format(resp=dumpResp)
2184 except Exception as e:
2185 errorInfo += "BMC dump list exception: {eInfo}\n".format(eInfo=e)
2186
2187 if dumpListCollected:
2188 output['fileList'] = []
2189 for dump in dumpList:
2190 try:
2191 if '/xyz/openbmc_project/dump/internal/manager' not in dump:
2192 d['dumpNum'] = int(dump.strip().split('/')[-1])
2193 print('retrieving dump file ' + str(d['dumpNum']))
2194 filename = bmcDumpRetrieve(host, args, session).split('Saved as ')[-1]
2195 output['fileList'].append(filename)
2196 except Exception as e:
2197 print("Unable to collect dump: {dumpInfo}".format(dumpInfo=dump))
2198 errorInfo += "Exception collecting a bmc dump {dumpInfo}\n {eInfo}\n".format(dumpInfo=dump, eInfo=e)
2199 output['errors'] = errorInfo
2200 return output
Justin Thalere412dc22018-01-12 16:28:24 -06002201
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002202def collectServiceData(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002203 """
2204 Collects all data needed for service from the BMC
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002205
Justin Thalere412dc22018-01-12 16:28:24 -06002206 @param host: string, the hostname or IP address of the bmc
2207 @param args: contains additional arguments used by the collectServiceData sub command
2208 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002209 @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 -06002210 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002211
Justin Thaler22b1bb52018-03-15 13:31:32 -05002212 global toolVersion
Justin Thaler666cf342019-01-23 14:44:27 -06002213 filelist = []
2214 errorInfo = ""
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002215
Justin Thaler666cf342019-01-23 14:44:27 -06002216 #get current number of bmc dumps and create a new bmc dump
2217 dumpInitdata = csdDumpInitiate(host, args, session)
2218 dumpcount = dumpInitdata['dumpcount']
2219 errorInfo += dumpInitdata['errors']
2220 #create the directory to put files
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002221 try:
2222 args.silent = True
Justin Thalercf1deae2018-05-25 19:35:21 -05002223 myDir = tempfile.gettempdir()+os.sep + host + "--" + datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%S")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002224 os.makedirs(myDir)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002225
Justin Thaler666cf342019-01-23 14:44:27 -06002226 except Exception as e:
2227 print('Unable to create the temporary directory for data collection. Ensure sufficient privileges to create temporary directory. Aborting.')
2228 return("Python exception: {eInfo}".format(eInfo = e))
2229
2230 #Collect Inventory
2231 inventoryData = csdInventory(host, args, session, myDir)
2232 if 'fileLoc' in inventoryData:
2233 filelist.append(inventoryData['fileLoc'])
2234 errorInfo += inventoryData['errors']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002235 #Read all the sensor and OCC status
Justin Thaler666cf342019-01-23 14:44:27 -06002236 sensorData = csdSensors(host,args,session,myDir)
2237 if 'fileLoc' in sensorData:
2238 filelist.append(sensorData['fileLoc'])
2239 errorInfo += sensorData['errors']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002240 #Collect all of the LEDs status
Justin Thaler666cf342019-01-23 14:44:27 -06002241 ledStatus = csdLEDs(host, args, session, myDir)
2242 if 'fileLoc' in ledStatus:
2243 filelist.append(ledStatus['fileLoc'])
2244 errorInfo += ledStatus['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002245
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002246 #Collect the bmc logs
Justin Thaler666cf342019-01-23 14:44:27 -06002247 selShort = csdSelShortList(host, args, session, myDir)
2248 if 'fileLoc' in selShort:
2249 filelist.append(selShort['fileLoc'])
2250 errorInfo += selShort['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002251
Justin Thaler666cf342019-01-23 14:44:27 -06002252 parsedSELs = csdParsedSels(host, args, session, myDir)
2253 if 'fileLoc' in parsedSELs:
2254 filelist.append(parsedSELs['fileLoc'])
2255 errorInfo += parsedSELs['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002256
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002257 #collect RAW bmc enumeration
Justin Thaler666cf342019-01-23 14:44:27 -06002258 bmcRaw = csdFullEnumeration(host, args, session, myDir)
2259 if 'fileLoc' in bmcRaw:
2260 filelist.append(bmcRaw['fileLoc'])
2261 errorInfo += bmcRaw['errors']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002262
Justin Thaler666cf342019-01-23 14:44:27 -06002263 #wait for new dump to finish being created
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002264 waitingForNewDump = True
2265 count = 0;
Justin Thaler666cf342019-01-23 14:44:27 -06002266 print("Waiting for new BMC dump to finish being created.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002267 while(waitingForNewDump):
Justin Thaler666cf342019-01-23 14:44:27 -06002268 dumpList = bmcDumpList(host, args, session)['data']
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002269 if len(dumpList) > dumpcount:
2270 waitingForNewDump = False
2271 break;
2272 elif(count>30):
2273 print("Timed out waiting for bmc to make a new dump file. Dump space may be full.")
2274 break;
2275 else:
2276 time.sleep(2)
2277 count += 1
Justin Thaler666cf342019-01-23 14:44:27 -06002278
2279 #collect all of the dump files
2280 getBMCDumps = csdCollectAllDumps(host, args, session, myDir)
2281 if 'fileList' in getBMCDumps:
2282 filelist+= getBMCDumps['fileList']
2283 errorInfo += getBMCDumps['errors']
2284
2285 #write the runtime errors to a file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002286 try:
Justin Thaler666cf342019-01-23 14:44:27 -06002287 with open(myDir +os.sep+'openbmctoolRuntimeErrors.txt', 'w') as f:
2288 f.write(errorInfo)
2289 print("OpenBMC tool runtime errors collected and stored in " + myDir + os.sep+ "openbmctoolRuntimeErrors.txt")
2290 filelist.append(myDir+os.sep+'openbmctoolRuntimeErrors.txt')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002291 except Exception as e:
Justin Thaler666cf342019-01-23 14:44:27 -06002292 print("Failed to write OpenBMC tool runtime errors to file system.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002293
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002294 #create the zip file
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002295 try:
Justin Thalercf1deae2018-05-25 19:35:21 -05002296 filename = myDir.split(tempfile.gettempdir()+os.sep)[-1] + "_" + toolVersion + '_openbmc.zip'
Justin Thaler666cf342019-01-23 14:44:27 -06002297 zf = zipfile.ZipFile(myDir+os.sep + filename, 'w')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002298 for myfile in filelist:
2299 zf.write(myfile, os.path.basename(myfile))
2300 zf.close()
Justin Thaler666cf342019-01-23 14:44:27 -06002301 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 -06002302 except Exception as e:
2303 print("Failed to create zip file with collected information")
Justin Thaler666cf342019-01-23 14:44:27 -06002304 return "data collection finished"
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002305
Justin Thalere412dc22018-01-12 16:28:24 -06002306
2307def healthCheck(host, args, session):
2308 """
2309 runs a health check on the platform
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002310
Justin Thalere412dc22018-01-12 16:28:24 -06002311 @param host: string, the hostname or IP address of the bmc
2312 @param args: contains additional arguments used by the bmc sub command
2313 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002314 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2315 """
Justin Thalere412dc22018-01-12 16:28:24 -06002316 #check fru status and get as json to easily work through
2317 d = vars(args)
2318 useJson = d['json']
2319 d['json'] = True
2320 d['verbose']= False
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002321
Justin Thalere412dc22018-01-12 16:28:24 -06002322 frus = json.loads(fruStatus(host, args, session))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002323
Justin Thalere412dc22018-01-12 16:28:24 -06002324 hwStatus= "OK"
2325 performanceStatus = "OK"
2326 for key in frus:
2327 if frus[key]["Functional"] == "No" and frus[key]["Present"] == "Yes":
2328 hwStatus= "Degraded"
Justin Thalerfb9c81c2018-07-16 11:14:37 -05002329 if("power_supply" in key or "powersupply" in key):
2330 gpuCount =0
2331 for comp in frus:
Justin Thalere412dc22018-01-12 16:28:24 -06002332 if "gv100card" in comp:
2333 gpuCount +=1
2334 if gpuCount > 4:
2335 hwStatus = "Critical"
2336 performanceStatus="Degraded"
2337 break;
2338 elif("fan" in key):
2339 hwStatus = "Degraded"
2340 else:
2341 performanceStatus = "Degraded"
2342 if useJson:
2343 output = {"Hardware Status": hwStatus, "Performance": performanceStatus}
2344 output = json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
2345 else:
2346 output = ("Hardware Status: " + hwStatus +
2347 "\nPerformance: " +performanceStatus )
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002348
2349
Justin Thalere412dc22018-01-12 16:28:24 -06002350 #SW407886: Clear the duplicate entries
2351 #collect the dups
2352 d['devdebug'] = False
2353 sels = json.loads(selPrint(host, args, session))
2354 logNums2Clr = []
2355 oldestLogNum={"logNum": "bogus" ,"key" : ""}
2356 count = 0
2357 if sels['numAlerts'] > 0:
2358 for key in sels:
2359 if "numAlerts" in key:
2360 continue
2361 try:
2362 if "slave@00:00/00:00:00:06/sbefifo1-dev0/occ1-dev0" in sels[key]['Message']:
2363 count += 1
2364 if count > 1:
2365 #preserve first occurrence
2366 if sels[key]['timestamp'] < sels[oldestLogNum['key']]['timestamp']:
2367 oldestLogNum['key']=key
2368 oldestLogNum['logNum'] = sels[key]['logNum']
2369 else:
2370 oldestLogNum['key']=key
2371 oldestLogNum['logNum'] = sels[key]['logNum']
2372 logNums2Clr.append(sels[key]['logNum'])
2373 except KeyError:
2374 continue
2375 if(count >0):
2376 logNums2Clr.remove(oldestLogNum['logNum'])
2377 #delete the dups
2378 if count >1:
Justin Thalere412dc22018-01-12 16:28:24 -06002379 data = "{\"data\": [] }"
2380 for logNum in logNums2Clr:
2381 url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
2382 try:
Justin Thaler27197622019-01-23 14:42:11 -06002383 session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002384 except(requests.exceptions.Timeout):
2385 deleteFailed = True
2386 except(requests.exceptions.ConnectionError) as err:
2387 deleteFailed = True
2388 #End of defect resolve code
2389 d['json'] = useJson
2390 return output
2391
2392
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002393
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002394def bmc(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002395 """
2396 handles various bmc level commands, currently bmc rebooting
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002397
Justin Thalere412dc22018-01-12 16:28:24 -06002398 @param host: string, the hostname or IP address of the bmc
2399 @param args: contains additional arguments used by the bmc sub command
2400 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002401 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2402 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002403 if(args.type is not None):
2404 return bmcReset(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06002405 if(args.info):
2406 return "Not implemented at this time"
2407
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002408
Justin Thalere412dc22018-01-12 16:28:24 -06002409
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002410def bmcReset(host, args, session):
Justin Thalere412dc22018-01-12 16:28:24 -06002411 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002412 controls resetting the bmc. warm reset reboots the bmc, cold reset removes the configuration and reboots.
2413
Justin Thalere412dc22018-01-12 16:28:24 -06002414 @param host: string, the hostname or IP address of the bmc
2415 @param args: contains additional arguments used by the bmcReset sub command
2416 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002417 @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
2418 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002419 if checkFWactivation(host, args, session):
2420 return ("BMC reset control disabled during firmware activation")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002421 if(args.type == "warm"):
2422 print("\nAttempting to reboot the BMC...:")
2423 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06002424 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06002425 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002426 return res.text
2427 elif(args.type =="cold"):
Justin Thalere412dc22018-01-12 16:28:24 -06002428 print("\nAttempting to reboot the BMC...:")
2429 url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
Justin Thalere412dc22018-01-12 16:28:24 -06002430 data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
Justin Thaler27197622019-01-23 14:42:11 -06002431 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002432 return res.text
Justin Thalerf9aee3e2017-12-05 12:11:09 -06002433 else:
2434 return "invalid command"
Justin Thalere412dc22018-01-12 16:28:24 -06002435
2436def gardClear(host, args, session):
2437 """
2438 clears the gard records from the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002439
Justin Thalere412dc22018-01-12 16:28:24 -06002440 @param host: string, the hostname or IP address of the bmc
2441 @param args: contains additional arguments used by the gardClear sub command
2442 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002443 """
Justin Thalere412dc22018-01-12 16:28:24 -06002444 url="https://"+host+"/org/open_power/control/gard/action/Reset"
Justin Thalere412dc22018-01-12 16:28:24 -06002445 data = '{"data":[]}'
2446 try:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002447
Justin Thaler27197622019-01-23 14:42:11 -06002448 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002449 if res.status_code == 404:
2450 return "Command not supported by this firmware version"
2451 else:
2452 return res.text
2453 except(requests.exceptions.Timeout):
2454 return connectionErrHandler(args.json, "Timeout", None)
2455 except(requests.exceptions.ConnectionError) as err:
2456 return connectionErrHandler(args.json, "ConnectionError", err)
2457
2458def activateFWImage(host, args, session):
2459 """
2460 activates a firmware image on the bmc
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002461
Justin Thalere412dc22018-01-12 16:28:24 -06002462 @param host: string, the hostname or IP address of the bmc
2463 @param args: contains additional arguments used by the fwflash sub command
2464 @param session: the active session to use
2465 @param fwID: the unique ID of the fw image to activate
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002466 """
Justin Thalere412dc22018-01-12 16:28:24 -06002467 fwID = args.imageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002468
Justin Thalere412dc22018-01-12 16:28:24 -06002469 #determine the existing versions
Justin Thalere412dc22018-01-12 16:28:24 -06002470 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2471 try:
Justin Thaler27197622019-01-23 14:42:11 -06002472 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002473 except(requests.exceptions.Timeout):
2474 return connectionErrHandler(args.json, "Timeout", None)
2475 except(requests.exceptions.ConnectionError) as err:
2476 return connectionErrHandler(args.json, "ConnectionError", err)
2477 existingSoftware = json.loads(resp.text)['data']
2478 altVersionID = ''
2479 versionType = ''
2480 imageKey = '/xyz/openbmc_project/software/'+fwID
2481 if imageKey in existingSoftware:
2482 versionType = existingSoftware[imageKey]['Purpose']
2483 for key in existingSoftware:
2484 if imageKey == key:
2485 continue
2486 if 'Purpose' in existingSoftware[key]:
2487 if versionType == existingSoftware[key]['Purpose']:
2488 altVersionID = key.split('/')[-1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002489
2490
2491
2492
Justin Thalere412dc22018-01-12 16:28:24 -06002493 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/attr/Priority"
2494 url1="https://"+host+"/xyz/openbmc_project/software/"+ altVersionID + "/attr/Priority"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002495 data = "{\"data\": 0}"
Justin Thalere412dc22018-01-12 16:28:24 -06002496 data1 = "{\"data\": 1 }"
2497 try:
Justin Thaler27197622019-01-23 14:42:11 -06002498 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
2499 resp1 = session.put(url1, headers=jsonHeader, data=data1, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002500 except(requests.exceptions.Timeout):
2501 return connectionErrHandler(args.json, "Timeout", None)
2502 except(requests.exceptions.ConnectionError) as err:
2503 return connectionErrHandler(args.json, "ConnectionError", err)
2504 if(not args.json):
2505 if resp.status_code == 200 and resp1.status_code == 200:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002506 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 -06002507 else:
2508 return "Firmware activation failed."
2509 else:
2510 return resp.text + resp1.text
Justin Thaler22b1bb52018-03-15 13:31:32 -05002511
2512def activateStatus(host, args, session):
2513 if checkFWactivation(host, args, session):
2514 return("Firmware is currently being activated. Do not reboot the BMC or start the Host OS")
2515 else:
2516 return("No firmware activations are pending")
2517
2518def extractFWimage(path, imageType):
2519 """
2520 extracts the bmc image and returns information about the package
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002521
Justin Thaler22b1bb52018-03-15 13:31:32 -05002522 @param path: the path and file name of the firmware image
2523 @param imageType: The type of image the user is trying to flash. Host or BMC
2524 @return: the image id associated with the package. returns an empty string on error.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002525 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002526 f = tempfile.TemporaryFile()
2527 tmpDir = tempfile.gettempdir()
2528 newImageID = ""
2529 if os.path.exists(path):
2530 try:
2531 imageFile = tarfile.open(path,'r')
2532 contents = imageFile.getmembers()
2533 for tf in contents:
2534 if 'MANIFEST' in tf.name:
2535 imageFile.extract(tf.name, path=tmpDir)
2536 with open(tempfile.gettempdir() +os.sep+ tf.name, 'r') as imageInfo:
2537 for line in imageInfo:
2538 if 'purpose' in line:
2539 purpose = line.split('=')[1]
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002540 if imageType not in purpose.split('.')[-1]:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002541 print('The specified image is not for ' + imageType)
2542 print('Please try again with the image for ' + imageType)
2543 return ""
2544 if 'version' == line.split('=')[0]:
2545 version = line.split('=')[1].strip().encode('utf-8')
2546 m = hashlib.sha512()
2547 m.update(version)
2548 newImageID = m.hexdigest()[:8]
2549 break
2550 try:
2551 os.remove(tempfile.gettempdir() +os.sep+ tf.name)
2552 except OSError:
2553 pass
2554 return newImageID
2555 except tarfile.ExtractError as e:
2556 print('Unable to extract information from the firmware file.')
2557 print('Ensure you have write access to the directory: ' + tmpDir)
2558 return newImageID
2559 except tarfile.TarError as e:
2560 print('This is not a valid firmware file.')
2561 return newImageID
2562 print("This is not a valid firmware file.")
2563 return newImageID
2564 else:
2565 print('The filename and path provided are not valid.')
2566 return newImageID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002567
Justin Thaler22b1bb52018-03-15 13:31:32 -05002568def getAllFWImageIDs(fwInvDict):
2569 """
2570 gets a list of all the firmware image IDs
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002571
Justin Thaler22b1bb52018-03-15 13:31:32 -05002572 @param fwInvDict: the dictionary to search for FW image IDs
2573 @return: list containing string representation of the found image ids
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002574 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002575 idList = []
2576 for key in fwInvDict:
2577 if 'Version' in fwInvDict[key]:
2578 idList.append(key.split('/')[-1])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002579 return idList
2580
Justin Thalere412dc22018-01-12 16:28:24 -06002581def fwFlash(host, args, session):
2582 """
2583 updates the bmc firmware and pnor firmware
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002584
Justin Thalere412dc22018-01-12 16:28:24 -06002585 @param host: string, the hostname or IP address of the bmc
2586 @param args: contains additional arguments used by the fwflash sub command
2587 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002588 """
Justin Thaler22b1bb52018-03-15 13:31:32 -05002589 d = vars(args)
Justin Thalere412dc22018-01-12 16:28:24 -06002590 if(args.type == 'bmc'):
2591 purp = 'BMC'
2592 else:
2593 purp = 'Host'
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002594
2595 #check power state of the machine. No concurrent FW updates allowed
Justin Thaler22b1bb52018-03-15 13:31:32 -05002596 d['powcmd'] = 'status'
2597 powerstate = chassisPower(host, args, session)
2598 if 'Chassis Power State: On' in powerstate:
2599 return("Aborting firmware update. Host is powered on. Please turn off the host and try again.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002600
Justin Thaler22b1bb52018-03-15 13:31:32 -05002601 #determine the existing images on the bmc
Justin Thalere412dc22018-01-12 16:28:24 -06002602 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2603 try:
Justin Thaler27197622019-01-23 14:42:11 -06002604 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thalere412dc22018-01-12 16:28:24 -06002605 except(requests.exceptions.Timeout):
2606 return connectionErrHandler(args.json, "Timeout", None)
2607 except(requests.exceptions.ConnectionError) as err:
2608 return connectionErrHandler(args.json, "ConnectionError", err)
2609 oldsoftware = json.loads(resp.text)['data']
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002610
Justin Thaler22b1bb52018-03-15 13:31:32 -05002611 #Extract the tar and get information from the manifest file
2612 newversionID = extractFWimage(args.fileloc, purp)
2613 if newversionID == "":
2614 return "Unable to verify FW image."
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002615
2616
Justin Thaler22b1bb52018-03-15 13:31:32 -05002617 #check if the new image is already on the bmc
2618 if newversionID not in getAllFWImageIDs(oldsoftware):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002619
Justin Thaler22b1bb52018-03-15 13:31:32 -05002620 #upload the file
2621 httpHeader = {'Content-Type':'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002622 httpHeader.update(xAuthHeader)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002623 url="https://"+host+"/upload/image"
2624 data=open(args.fileloc,'rb').read()
2625 print("Uploading file to BMC")
Justin Thalere412dc22018-01-12 16:28:24 -06002626 try:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002627 resp = session.post(url, headers=httpHeader, data=data, verify=False)
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)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002632 if resp.status_code != 200:
2633 return "Failed to upload the file to the bmc"
Justin Thalere412dc22018-01-12 16:28:24 -06002634 else:
Justin Thaler22b1bb52018-03-15 13:31:32 -05002635 print("Upload complete.")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002636
Justin Thaler22b1bb52018-03-15 13:31:32 -05002637 #verify bmc processed the image
2638 software ={}
2639 for i in range(0, 5):
Justin Thaler22b1bb52018-03-15 13:31:32 -05002640 url="https://"+host+"/xyz/openbmc_project/software/enumerate"
2641 try:
Justin Thaler27197622019-01-23 14:42:11 -06002642 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002643 except(requests.exceptions.Timeout):
2644 return connectionErrHandler(args.json, "Timeout", None)
2645 except(requests.exceptions.ConnectionError) as err:
2646 return connectionErrHandler(args.json, "ConnectionError", err)
2647 software = json.loads(resp.text)['data']
2648 #check if bmc is done processing the new image
2649 if (newversionID in getAllFWImageIDs(software)):
Justin Thalere412dc22018-01-12 16:28:24 -06002650 break
Justin Thaler22b1bb52018-03-15 13:31:32 -05002651 else:
2652 time.sleep(15)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002653
Justin Thaler22b1bb52018-03-15 13:31:32 -05002654 #activate the new image
2655 print("Activating new image: "+newversionID)
2656 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID + "/attr/RequestedActivation"
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002657 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05002658 try:
Justin Thaler27197622019-01-23 14:42:11 -06002659 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002660 except(requests.exceptions.Timeout):
2661 return connectionErrHandler(args.json, "Timeout", None)
2662 except(requests.exceptions.ConnectionError) as err:
2663 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002664
Justin Thaler22b1bb52018-03-15 13:31:32 -05002665 #wait for the activation to complete, timeout after ~1 hour
2666 i=0
2667 while i < 360:
2668 url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002669 data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
Justin Thaler22b1bb52018-03-15 13:31:32 -05002670 try:
Justin Thaler27197622019-01-23 14:42:11 -06002671 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler22b1bb52018-03-15 13:31:32 -05002672 except(requests.exceptions.Timeout):
2673 return connectionErrHandler(args.json, "Timeout", None)
2674 except(requests.exceptions.ConnectionError) as err:
2675 return connectionErrHandler(args.json, "ConnectionError", err)
2676 fwInfo = json.loads(resp.text)['data']
2677 if 'Activating' not in fwInfo['Activation'] and 'Activating' not in fwInfo['RequestedActivation']:
2678 print('')
2679 break
2680 else:
2681 sys.stdout.write('.')
2682 sys.stdout.flush()
2683 time.sleep(10) #check every 10 seconds
2684 return "Firmware flash and activation completed. Please reboot the bmc and then boot the host OS for the changes to take effect. "
2685 else:
2686 print("This image has been found on the bmc. Activating image: " + newversionID)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002687
Justin Thaler22b1bb52018-03-15 13:31:32 -05002688 d['imageID'] = newversionID
2689 return activateFWImage(host, args, session)
Justin Thalere412dc22018-01-12 16:28:24 -06002690
Justin Thaler3d71d402018-07-24 14:35:39 -05002691def getFWInventoryAttributes(rawFWInvItem, ID):
2692 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002693 gets and lists all of the firmware in the system.
2694
Justin Thaler3d71d402018-07-24 14:35:39 -05002695 @return: returns a dictionary containing the image attributes
2696 """
2697 reqActivation = rawFWInvItem["RequestedActivation"].split('.')[-1]
2698 pendingActivation = ""
2699 if reqActivation == "None":
2700 pendingActivation = "No"
2701 else:
2702 pendingActivation = "Yes"
2703 firmwareAttr = {ID: {
2704 "Purpose": rawFWInvItem["Purpose"].split('.')[-1],
2705 "Version": rawFWInvItem["Version"],
2706 "RequestedActivation": pendingActivation,
2707 "ID": ID}}
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002708
Justin Thaler3d71d402018-07-24 14:35:39 -05002709 if "ExtendedVersion" in rawFWInvItem:
2710 firmwareAttr[ID]['ExtendedVersion'] = rawFWInvItem['ExtendedVersion'].split(',')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002711 else:
Justin Thaler3d71d402018-07-24 14:35:39 -05002712 firmwareAttr[ID]['ExtendedVersion'] = ""
2713 return firmwareAttr
2714
2715def parseFWdata(firmwareDict):
2716 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002717 creates a dictionary with parsed firmware data
2718
Justin Thaler3d71d402018-07-24 14:35:39 -05002719 @return: returns a dictionary containing the image attributes
2720 """
2721 firmwareInfoDict = {"Functional": {}, "Activated":{}, "NeedsActivated":{}}
2722 for key in firmwareDict['data']:
2723 #check for valid endpoint
2724 if "Purpose" in firmwareDict['data'][key]:
2725 id = key.split('/')[-1]
2726 if firmwareDict['data'][key]['Activation'].split('.')[-1] == "Active":
2727 fwActivated = True
2728 else:
2729 fwActivated = False
Justin Thalercb68e062019-03-26 19:04:52 -05002730 if 'Priority' in firmwareDict['data'][key]:
2731 if firmwareDict['data'][key]['Priority'] == 0:
2732 firmwareInfoDict['Functional'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2733 elif firmwareDict['data'][key]['Priority'] >= 0 and fwActivated:
2734 firmwareInfoDict['Activated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
2735 else:
2736 firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
Justin Thaler3d71d402018-07-24 14:35:39 -05002737 else:
Justin Thalercb68e062019-03-26 19:04:52 -05002738 firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
Justin Thaler3d71d402018-07-24 14:35:39 -05002739 emptySections = []
2740 for key in firmwareInfoDict:
2741 if len(firmwareInfoDict[key])<=0:
2742 emptySections.append(key)
2743 for key in emptySections:
2744 del firmwareInfoDict[key]
2745 return firmwareInfoDict
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002746
Justin Thaler3d71d402018-07-24 14:35:39 -05002747def displayFWInvenory(firmwareInfoDict, args):
2748 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002749 gets and lists all of the firmware in the system.
2750
Justin Thaler3d71d402018-07-24 14:35:39 -05002751 @return: returns a string containing all of the firmware information
2752 """
2753 output = ""
2754 if not args.json:
2755 for key in firmwareInfoDict:
2756 for subkey in firmwareInfoDict[key]:
2757 firmwareInfoDict[key][subkey]['ExtendedVersion'] = str(firmwareInfoDict[key][subkey]['ExtendedVersion'])
2758 if not args.verbose:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002759 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002760 colNames = ["Purpose", "Version", "ID"]
2761 keylist = ["Purpose", "Version", "ID"]
2762 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2763 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002764 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002765 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2766 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002767 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002768 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002769
Justin Thaler3d71d402018-07-24 14:35:39 -05002770 else:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002771 output = "---Running Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002772 colNames = ["Purpose", "Version", "ID", "Pending Activation", "Extended Version"]
2773 keylist = ["Purpose", "Version", "ID", "RequestedActivation", "ExtendedVersion"]
2774 output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
2775 if "Activated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002776 output += "\n---Available Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002777 output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
2778 if "NeedsActivated" in firmwareInfoDict:
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002779 output += "\n---Needs Activated Images---\n"
Justin Thaler3d71d402018-07-24 14:35:39 -05002780 output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
2781 return output
2782 else:
2783 return str(json.dumps(firmwareInfoDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
2784
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002785def firmwareList(host, args, session):
Justin Thaler3d71d402018-07-24 14:35:39 -05002786 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002787 gets and lists all of the firmware in the system.
2788
Justin Thaler3d71d402018-07-24 14:35:39 -05002789 @return: returns a string containing all of the firmware information
2790 """
Justin Thaler3d71d402018-07-24 14:35:39 -05002791 url="https://{hostname}/xyz/openbmc_project/software/enumerate".format(hostname=host)
2792 try:
Justin Thaler27197622019-01-23 14:42:11 -06002793 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Justin Thaler3d71d402018-07-24 14:35:39 -05002794 except(requests.exceptions.Timeout):
2795 return(connectionErrHandler(args.json, "Timeout", None))
2796 firmwareDict = json.loads(res.text)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002797
Justin Thaler3d71d402018-07-24 14:35:39 -05002798 #sort the received information
2799 firmwareInfoDict = parseFWdata(firmwareDict)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002800
Justin Thaler3d71d402018-07-24 14:35:39 -05002801 #display the information
2802 return displayFWInvenory(firmwareInfoDict, args)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002803
2804
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002805def deleteFWVersion(host, args, session):
2806 """
2807 deletes a firmware version on the BMC
2808
2809 @param host: string, the hostname or IP address of the BMC
2810 @param args: contains additional arguments used by the fwflash sub command
2811 @param session: the active session to use
2812 @param fwID: the unique ID of the fw version to delete
2813 """
2814 fwID = args.versionID
2815
2816 print("Deleting version: "+fwID)
2817 url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/action/Delete"
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002818 data = "{\"data\": [] }"
2819
2820 try:
Justin Thaler27197622019-01-23 14:42:11 -06002821 res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06002822 except(requests.exceptions.Timeout):
2823 return(connectionErrHandler(args.json, "Timeout", None))
2824 if res.status_code == 200:
2825 return ('The firmware version has been deleted')
2826 else:
2827 return ('Unable to delete the specified firmware version')
2828
2829
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002830def restLogging(host, args, session):
2831 """
2832 Called by the logging function. Turns REST API logging on/off.
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002833
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002834 @param host: string, the hostname or IP address of the bmc
2835 @param args: contains additional arguments used by the logging sub command
2836 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002837 @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 -05002838 """
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002839 url="https://"+host+"/xyz/openbmc_project/logging/rest_api_logs/attr/Enabled"
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002840
2841 if(args.rest_logging == 'on'):
2842 data = '{"data": 1}'
2843 elif(args.rest_logging == 'off'):
2844 data = '{"data": 0}'
2845 else:
2846 return "Invalid logging rest_api command"
2847
2848 try:
Justin Thaler27197622019-01-23 14:42:11 -06002849 res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05002850 except(requests.exceptions.Timeout):
2851 return(connectionErrHandler(args.json, "Timeout", None))
2852 return res.text
2853
2854
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002855def remoteLogging(host, args, session):
2856 """
2857 Called by the logging function. View config information for/disable remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002858
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002859 @param host: string, the hostname or IP address of the bmc
2860 @param args: contains additional arguments used by the logging sub command
2861 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002862 @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 -05002863 """
2864
2865 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002866
2867 try:
2868 if(args.remote_logging == 'view'):
Justin Thaler27197622019-01-23 14:42:11 -06002869 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002870 elif(args.remote_logging == 'disable'):
Justin Thaler27197622019-01-23 14:42:11 -06002871 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": 0}, verify=False, timeout=baseTimeout)
2872 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": ""}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002873 else:
2874 return "Invalid logging remote_logging command"
2875 except(requests.exceptions.Timeout):
2876 return(connectionErrHandler(args.json, "Timeout", None))
2877 return res.text
2878
2879
2880def remoteLoggingConfig(host, args, session):
2881 """
2882 Called by the logging function. Configures remote logging (rsyslog).
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002883
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002884 @param host: string, the hostname or IP address of the bmc
2885 @param args: contains additional arguments used by the logging sub command
2886 @param session: the active session to use
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06002887 @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 -05002888 """
2889
2890 url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002891
2892 try:
Justin Thaler27197622019-01-23 14:42:11 -06002893 res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": args.port}, verify=False, timeout=baseTimeout)
2894 res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": args.address}, verify=False, timeout=baseTimeout)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002895 except(requests.exceptions.Timeout):
2896 return(connectionErrHandler(args.json, "Timeout", None))
2897 return res.text
2898
Marri Devender Rao82590dc2019-06-06 04:54:22 -05002899def redfishSupportPresent(host, session):
2900 url = "https://" + host + "/redfish/v1"
2901 try:
2902 resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
2903 except(requests.exceptions.Timeout):
2904 return False
2905 except(requests.exceptions.ConnectionError) as err:
2906 return False
2907 if resp.status_code != 200:
2908 return False
2909 else:
2910 return True
Ratan Gupta9166cd22018-10-01 18:09:40 +05302911
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002912def certificateUpdate(host, args, session):
2913 """
2914 Called by certificate management function. update server/client/authority certificates
2915 Example:
2916 certificate update server https -f cert.pem
2917 certificate update authority ldap -f Root-CA.pem
2918 certificate update client ldap -f cert.pem
2919 @param host: string, the hostname or IP address of the bmc
2920 @param args: contains additional arguments used by the certificate update sub command
2921 @param session: the active session to use
2922 """
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002923 httpHeader = {'Content-Type': 'application/octet-stream'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002924 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002925 data = open(args.fileloc, 'rb').read()
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002926 try:
Marri Devender Rao82590dc2019-06-06 04:54:22 -05002927 if redfishSupportPresent(host, session):
Marri Devender Rao62db08a2019-08-22 03:16:02 -05002928 if(args.type.lower() == 'server' and args.service.lower() != "https"):
2929 return "Invalid service type"
2930 if(args.type.lower() == 'client' and args.service.lower() != "ldap"):
2931 return "Invalid service type"
2932 if(args.type.lower() == 'authority' and args.service.lower() != "ldap"):
2933 return "Invalid service type"
Marri Devender Rao82590dc2019-06-06 04:54:22 -05002934 url = "";
2935 if(args.type.lower() == 'server'):
2936 url = "https://" + host + \
2937 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"
2938 elif(args.type.lower() == 'client'):
2939 url = "https://" + host + \
2940 "/redfish/v1/AccountService/LDAP/Certificates"
2941 elif(args.type.lower() == 'authority'):
2942 url = "https://" + host + \
2943 "/redfish/v1/Managers/bmc/Truststore/Certificates"
2944 else:
2945 return "Unsupported certificate type"
2946 resp = session.post(url, headers=httpHeader, data=data,
2947 verify=False)
2948 else:
2949 url = "https://" + host + "/xyz/openbmc_project/certs/" + \
2950 args.type.lower() + "/" + args.service.lower()
2951 resp = session.put(url, headers=httpHeader, data=data, verify=False)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002952 except(requests.exceptions.Timeout):
2953 return(connectionErrHandler(args.json, "Timeout", None))
2954 except(requests.exceptions.ConnectionError) as err:
2955 return connectionErrHandler(args.json, "ConnectionError", err)
2956 if resp.status_code != 200:
2957 print(resp.text)
2958 return "Failed to update the certificate"
2959 else:
Marri Devender Rao82590dc2019-06-06 04:54:22 -05002960 print("Update complete.")
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002961
2962def certificateDelete(host, args, session):
2963 """
2964 Called by certificate management function to delete certificate
2965 Example:
2966 certificate delete server https
2967 certificate delete authority ldap
2968 certificate delete client ldap
2969 @param host: string, the hostname or IP address of the bmc
2970 @param args: contains additional arguments used by the certificate delete sub command
2971 @param session: the active session to use
2972 """
Marri Devender Rao77e78682019-07-17 03:18:35 -05002973 if redfishSupportPresent(host, session):
2974 return "Not supported, please use certificate replace instead";
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002975 httpHeader = {'Content-Type': 'multipart/form-data'}
Matt Spinler220c3c42019-01-04 15:09:29 -06002976 httpHeader.update(xAuthHeader)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05002977 url = "https://" + host + "/xyz/openbmc_project/certs/" + args.type.lower() + "/" + args.service.lower()
2978 print("Deleting certificate url=" + url)
2979 try:
2980 resp = session.delete(url, headers=httpHeader)
2981 except(requests.exceptions.Timeout):
2982 return(connectionErrHandler(args.json, "Timeout", None))
2983 except(requests.exceptions.ConnectionError) as err:
2984 return connectionErrHandler(args.json, "ConnectionError", err)
2985 if resp.status_code != 200:
2986 print(resp.text)
2987 return "Failed to delete the certificate"
2988 else:
Marri Devender Rao77e78682019-07-17 03:18:35 -05002989 print("Delete complete.")
Deepak Kodihalli02d53282018-09-18 06:53:31 -05002990
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05002991def certificateReplace(host, args, session):
2992 """
2993 Called by certificate management function. replace server/client/
2994 authority certificates
2995 Example:
2996 certificate replace server https -f cert.pem
2997 certificate replace authority ldap -f Root-CA.pem
2998 certificate replace client ldap -f cert.pem
2999 @param host: string, the hostname or IP address of the bmc
3000 @param args: contains additional arguments used by the certificate
3001 replace sub command
3002 @param session: the active session to use
3003 """
3004 cert = open(args.fileloc, 'rb').read()
3005 try:
3006 if redfishSupportPresent(host, session):
3007 httpHeader = {'Content-Type': 'application/json'}
3008 httpHeader.update(xAuthHeader)
3009 url = "";
Marri Devender Rao62db08a2019-08-22 03:16:02 -05003010 if(args.type.lower() == 'server' and args.service.lower() != "https"):
3011 return "Invalid service type"
3012 if(args.type.lower() == 'client' and args.service.lower() != "ldap"):
3013 return "Invalid service type"
3014 if(args.type.lower() == 'authority' and args.service.lower() != "ldap"):
3015 return "Invalid service type"
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05003016 if(args.type.lower() == 'server'):
3017 url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
3018 elif(args.type.lower() == 'client'):
3019 url = "/redfish/v1/AccountService/LDAP/Certificates/1"
3020 elif(args.type.lower() == 'authority'):
3021 url = "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
3022 replaceUrl = "https://" + host + \
3023 "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"
3024 data ={"CertificateUri":{"@odata.id":url}, "CertificateType":"PEM",
3025 "CertificateString":cert}
3026 resp = session.post(replaceUrl, headers=httpHeader, json=data, verify=False)
3027 else:
3028 httpHeader = {'Content-Type': 'application/octet-stream'}
3029 httpHeader.update(xAuthHeader)
3030 url = "https://" + host + "/xyz/openbmc_project/certs/" + \
3031 args.type.lower() + "/" + args.service.lower()
3032 resp = session.delete(url, headers=httpHeader)
3033 resp = session.put(url, headers=httpHeader, data=cert, verify=False)
3034 except(requests.exceptions.Timeout):
3035 return(connectionErrHandler(args.json, "Timeout", None))
3036 except(requests.exceptions.ConnectionError) as err:
3037 return connectionErrHandler(args.json, "ConnectionError", err)
3038 if resp.status_code != 200:
3039 print(resp.text)
3040 return "Failed to replace the certificate"
3041 else:
3042 print("Replace complete.")
3043 return resp.text
3044
Marri Devender Rao34646402019-07-01 05:46:03 -05003045def certificateDisplay(host, args, session):
3046 """
3047 Called by certificate management function. display server/client/
3048 authority certificates
3049 Example:
3050 certificate display server
3051 certificate display authority
3052 certificate display client
3053 @param host: string, the hostname or IP address of the bmc
3054 @param args: contains additional arguments used by the certificate
3055 display sub command
3056 @param session: the active session to use
3057 """
3058 if not redfishSupportPresent(host, session):
3059 return "Not supported";
3060
3061 httpHeader = {'Content-Type': 'application/octet-stream'}
3062 httpHeader.update(xAuthHeader)
3063 if(args.type.lower() == 'server'):
3064 url = "https://" + host + \
3065 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
3066 elif(args.type.lower() == 'client'):
3067 url = "https://" + host + \
3068 "/redfish/v1/AccountService/LDAP/Certificates/1"
3069 elif(args.type.lower() == 'authority'):
3070 url = "https://" + host + \
3071 "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
3072 try:
3073 resp = session.get(url, headers=httpHeader, verify=False)
3074 except(requests.exceptions.Timeout):
3075 return(connectionErrHandler(args.json, "Timeout", None))
3076 except(requests.exceptions.ConnectionError) as err:
3077 return connectionErrHandler(args.json, "ConnectionError", err)
3078 if resp.status_code != 200:
3079 print(resp.text)
3080 return "Failed to display the certificate"
3081 else:
3082 print("Display complete.")
3083 return resp.text
3084
Marri Devender Raoa208ff82019-07-01 05:51:27 -05003085def certificateList(host, args, session):
3086 """
3087 Called by certificate management function.
3088 Example:
3089 certificate list
3090 @param host: string, the hostname or IP address of the bmc
3091 @param args: contains additional arguments used by the certificate
3092 list sub command
3093 @param session: the active session to use
3094 """
3095 if not redfishSupportPresent(host, session):
3096 return "Not supported";
3097
3098 httpHeader = {'Content-Type': 'application/octet-stream'}
3099 httpHeader.update(xAuthHeader)
3100 url = "https://" + host + \
3101 "/redfish/v1/CertificateService/CertificateLocations/"
3102 try:
3103 resp = session.get(url, headers=httpHeader, verify=False)
3104 except(requests.exceptions.Timeout):
3105 return(connectionErrHandler(args.json, "Timeout", None))
3106 except(requests.exceptions.ConnectionError) as err:
3107 return connectionErrHandler(args.json, "ConnectionError", err)
3108 if resp.status_code != 200:
3109 print(resp.text)
3110 return "Failed to list certificates"
3111 else:
3112 print("List certificates complete.")
3113 return resp.text
3114
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003115def certificateGenerateCSR(host, args, session):
3116 """
3117 Called by certificate management function. Generate CSR for server/
3118 client certificates
3119 Example:
Marri Devender Raodf0e1a42019-09-09 08:18:27 -05003120 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
3121 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 -05003122 @param host: string, the hostname or IP address of the bmc
3123 @param args: contains additional arguments used by the certificate replace sub command
3124 @param session: the active session to use
3125 """
3126 if not redfishSupportPresent(host, session):
3127 return "Not supported";
3128
3129 httpHeader = {'Content-Type': 'application/octet-stream'}
3130 httpHeader.update(xAuthHeader)
3131 url = "";
3132 if(args.type.lower() == 'server'):
3133 url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
Marri Devender Rao88064f02019-08-19 09:00:30 -05003134 usage_list = ["ServerAuthentication"]
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003135 elif(args.type.lower() == 'client'):
3136 url = "/redfish/v1/AccountService/LDAP/Certificates/"
Marri Devender Rao88064f02019-08-19 09:00:30 -05003137 usage_list = ["ClientAuthentication"]
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003138 elif(args.type.lower() == 'authority'):
3139 url = "/redfish/v1/Managers/bmc/Truststore/Certificates/"
3140 print("Generating CSR url=" + url)
3141 generateCSRUrl = "https://" + host + \
3142 "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"
3143 try:
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003144 alt_name_list = args.alternativeNames.split(",")
3145 data ={"CertificateCollection":{"@odata.id":url},
3146 "CommonName":args.commonName, "City":args.city,
3147 "Country":args.country, "Organization":args.organization,
3148 "OrganizationalUnit":args.organizationUnit, "State":args.state,
Marri Devender Raodf0e1a42019-09-09 08:18:27 -05003149 "KeyPairAlgorithm":args.keyPairAlgorithm, "KeyCurveId":args.keyCurveId,
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05003150 "AlternativeNames":alt_name_list, "ContactPerson":args.contactPerson,
3151 "Email":args.email, "GivenName":args.givenname, "Initials":args.initials,
3152 "KeyUsage":usage_list, "Surname":args.surname,
3153 "UnstructuredName":args.unstructuredname}
3154 resp = session.post(generateCSRUrl, headers=httpHeader,
3155 json=data, verify=False)
3156 except(requests.exceptions.Timeout):
3157 return(connectionErrHandler(args.json, "Timeout", None))
3158 except(requests.exceptions.ConnectionError) as err:
3159 return connectionErrHandler(args.json, "ConnectionError", err)
3160 if resp.status_code != 200:
3161 print(resp.text)
3162 return "Failed to generate CSR"
3163 else:
3164 print("GenerateCSR complete.")
3165 return resp.text
3166
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003167def enableLDAPConfig(host, args, session):
Ratan Gupta9166cd22018-10-01 18:09:40 +05303168 """
3169 Called by the ldap function. Configures LDAP.
3170
3171 @param host: string, the hostname or IP address of the bmc
3172 @param args: contains additional arguments used by the ldap subcommand
3173 @param session: the active session to use
3174 @param args.json: boolean, if this flag is set to true, the output will
3175 be provided in json format for programmatic consumption
3176 """
3177
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003178 if(isRedfishSupport):
3179 return enableLDAP(host, args, session)
3180 else:
3181 return enableLegacyLDAP(host, args, session)
3182
3183def enableLegacyLDAP(host, args, session):
3184 """
3185 Called by the ldap function. Configures LDAP on Lagecy systems.
3186
3187 @param host: string, the hostname or IP address of the bmc
3188 @param args: contains additional arguments used by the ldap subcommand
3189 @param session: the active session to use
3190 @param args.json: boolean, if this flag is set to true, the output will
3191 be provided in json format for programmatic consumption
3192 """
3193
Ratan Gupta9166cd22018-10-01 18:09:40 +05303194 url='https://'+host+'/xyz/openbmc_project/user/ldap/action/CreateConfig'
Ratan Gupta9166cd22018-10-01 18:09:40 +05303195 scope = {
3196 'sub' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.sub',
3197 'one' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.one',
3198 'base': 'xyz.openbmc_project.User.Ldap.Create.SearchScope.base'
3199 }
3200
3201 serverType = {
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003202 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Create.Type.ActiveDirectory',
3203 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Create.Type.OpenLdap'
Ratan Gupta9166cd22018-10-01 18:09:40 +05303204 }
3205
3206 data = {"data": [args.uri, args.bindDN, args.baseDN, args.bindPassword, scope[args.scope], serverType[args.serverType]]}
3207
3208 try:
Justin Thaler27197622019-01-23 14:42:11 -06003209 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Ratan Gupta9166cd22018-10-01 18:09:40 +05303210 except(requests.exceptions.Timeout):
3211 return(connectionErrHandler(args.json, "Timeout", None))
3212 except(requests.exceptions.ConnectionError) as err:
3213 return connectionErrHandler(args.json, "ConnectionError", err)
3214
3215 return res.text
3216
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003217def enableLDAP(host, args, session):
3218 """
3219 Called by the ldap function. Configures LDAP for systems with latest user-manager design changes
3220
3221 @param host: string, the hostname or IP address of the bmc
3222 @param args: contains additional arguments used by the ldap subcommand
3223 @param session: the active session to use
3224 @param args.json: boolean, if this flag is set to true, the output will
3225 be provided in json format for programmatic consumption
3226 """
3227
3228 scope = {
3229 'sub' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.sub',
3230 'one' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.one',
3231 'base': 'xyz.openbmc_project.User.Ldap.Config.SearchScope.base'
3232 }
3233
3234 serverType = {
3235 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Config.Type.ActiveDirectory',
3236 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap'
3237 }
3238
3239 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
3240
3241 serverTypeEnabled = getLDAPTypeEnabled(host,session)
3242 serverTypeToBeEnabled = args.serverType
3243
3244 #If the given LDAP type is already enabled, then return
3245 if (serverTypeToBeEnabled == serverTypeEnabled):
3246 return("Server type " + serverTypeToBeEnabled + " is already enabled...")
3247
3248 try:
3249
3250 # Copy the role map from the currently enabled LDAP server type
3251 # to the newly enabled server type
3252 # Disable the currently enabled LDAP server type. Unless
3253 # it is disabled, we cannot enable a new LDAP server type
3254 if (serverTypeEnabled is not None):
3255
3256 if (serverTypeToBeEnabled != serverTypeEnabled):
3257 res = syncRoleMap(host,args,session,serverTypeEnabled,serverTypeToBeEnabled)
3258
3259 data = "{\"data\": 0 }"
3260 res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3261
3262 data = {"data": args.baseDN}
3263 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBaseDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3264 if (res.status_code != requests.codes.ok):
3265 print("Updates to the property LDAPBaseDN failed...")
3266 return(res.text)
3267
3268 data = {"data": args.bindDN}
3269 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3270 if (res.status_code != requests.codes.ok):
3271 print("Updates to the property LDAPBindDN failed...")
3272 return(res.text)
3273
3274 data = {"data": args.bindPassword}
3275 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDNPassword', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3276 if (res.status_code != requests.codes.ok):
3277 print("Updates to the property LDAPBindDNPassword failed...")
3278 return(res.text)
3279
3280 data = {"data": scope[args.scope]}
3281 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPSearchScope', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3282 if (res.status_code != requests.codes.ok):
3283 print("Updates to the property LDAPSearchScope failed...")
3284 return(res.text)
3285
3286 data = {"data": args.uri}
3287 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPServerURI', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3288 if (res.status_code != requests.codes.ok):
3289 print("Updates to the property LDAPServerURI failed...")
3290 return(res.text)
3291
3292 data = {"data": args.groupAttrName}
3293 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/GroupNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3294 if (res.status_code != requests.codes.ok):
3295 print("Updates to the property GroupNameAttribute failed...")
3296 return(res.text)
3297
3298 data = {"data": args.userAttrName}
3299 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/UserNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3300 if (res.status_code != requests.codes.ok):
3301 print("Updates to the property UserNameAttribute failed...")
3302 return(res.text)
3303
3304 #After updating the properties, enable the new server type
3305 data = "{\"data\": 1 }"
3306 res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3307
3308 except(requests.exceptions.Timeout):
3309 return(connectionErrHandler(args.json, "Timeout", None))
3310 except(requests.exceptions.ConnectionError) as err:
3311 return connectionErrHandler(args.json, "ConnectionError", err)
3312 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05303313
3314def disableLDAP(host, args, session):
3315 """
3316 Called by the ldap function. Deletes the LDAP Configuration.
3317
3318 @param host: string, the hostname or IP address of the bmc
3319 @param args: contains additional arguments used by the ldap subcommand
3320 @param session: the active session to use
3321 @param args.json: boolean, if this flag is set to true, the output
3322 will be provided in json format for programmatic consumption
3323 """
3324
Ratan Gupta9166cd22018-10-01 18:09:40 +05303325 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05003326 if (isRedfishSupport) :
3327
3328 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
3329
3330 serverTypeEnabled = getLDAPTypeEnabled(host,session)
3331
3332 if (serverTypeEnabled is not None):
3333 #To keep the role map in sync,
3334 #If the server type being disabled has role map, then
3335 # - copy the role map to the other server type(s)
3336 for serverType in serverTypeMap.keys():
3337 if (serverType != serverTypeEnabled):
3338 res = syncRoleMap(host,args,session,serverTypeEnabled,serverType)
3339
3340 #Disable the currently enabled LDAP server type
3341 data = "{\"data\": 0 }"
3342 res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
3343
3344 else:
3345 return("LDAP server has not been enabled...")
3346
3347 else :
3348 url='https://'+host+'/xyz/openbmc_project/user/ldap/config/action/delete'
3349 data = {"data": []}
3350 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
3351
Ratan Gupta9166cd22018-10-01 18:09:40 +05303352 except(requests.exceptions.Timeout):
3353 return(connectionErrHandler(args.json, "Timeout", None))
3354 except(requests.exceptions.ConnectionError) as err:
3355 return connectionErrHandler(args.json, "ConnectionError", err)
3356
3357 return res.text
3358
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003359def enableDHCP(host, args, session):
3360
3361 """
3362 Called by the network function. Enables DHCP.
3363
3364 @param host: string, the hostname or IP address of the bmc
3365 @param args: contains additional arguments used by the ldap subcommand
3366 args.json: boolean, if this flag is set to true, the output
3367 will be provided in json format for programmatic consumption
3368 @param session: the active session to use
3369 """
3370
3371 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3372 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003373 data = "{\"data\": 1 }"
3374 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003375 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003376 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003377
3378 except(requests.exceptions.Timeout):
3379 return(connectionErrHandler(args.json, "Timeout", None))
3380 except(requests.exceptions.ConnectionError) as err:
3381 return connectionErrHandler(args.json, "ConnectionError", err)
3382 if res.status_code == 403:
3383 return "The specified Interface"+"("+args.Interface+")"+\
3384 " doesn't exist"
3385
3386 return res.text
3387
3388
3389def disableDHCP(host, args, session):
3390 """
3391 Called by the network function. Disables DHCP.
3392
3393 @param host: string, the hostname or IP address of the bmc
3394 @param args: contains additional arguments used by the ldap subcommand
3395 args.json: boolean, if this flag is set to true, the output
3396 will be provided in json format for programmatic consumption
3397 @param session: the active session to use
3398 """
3399
3400 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3401 "/attr/DHCPEnabled"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003402 data = "{\"data\": 0 }"
3403 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003404 res = session.put(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003405 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003406 except(requests.exceptions.Timeout):
3407 return(connectionErrHandler(args.json, "Timeout", None))
3408 except(requests.exceptions.ConnectionError) as err:
3409 return connectionErrHandler(args.json, "ConnectionError", err)
3410 if res.status_code == 403:
3411 return "The specified Interface"+"("+args.Interface+")"+\
3412 " doesn't exist"
3413 return res.text
3414
3415
3416def getHostname(host, args, session):
3417
3418 """
3419 Called by the network function. Prints out the Hostname.
3420
3421 @param host: string, the hostname or IP address of the bmc
3422 @param args: contains additional arguments used by the ldap subcommand
3423 args.json: boolean, if this flag is set to true, the output
3424 will be provided in json format for programmatic consumption
3425 @param session: the active session to use
3426 """
3427
3428 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003429
3430 try:
Justin Thaler27197622019-01-23 14:42:11 -06003431 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003432 except(requests.exceptions.Timeout):
3433 return(connectionErrHandler(args.json, "Timeout", None))
3434 except(requests.exceptions.ConnectionError) as err:
3435 return connectionErrHandler(args.json, "ConnectionError", err)
3436
3437 return res.text
3438
3439
3440def setHostname(host, args, session):
3441 """
3442 Called by the network function. Sets the Hostname.
3443
3444 @param host: string, the hostname or IP address of the bmc
3445 @param args: contains additional arguments used by the ldap subcommand
3446 args.json: boolean, if this flag is set to true, the output
3447 will be provided in json format for programmatic consumption
3448 @param session: the active session to use
3449 """
3450
3451 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003452
3453 data = {"data": args.HostName}
3454
3455 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003456 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003457 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003458 except(requests.exceptions.Timeout):
3459 return(connectionErrHandler(args.json, "Timeout", None))
3460 except(requests.exceptions.ConnectionError) as err:
3461 return connectionErrHandler(args.json, "ConnectionError", err)
3462
3463 return res.text
3464
3465
3466def getDomainName(host, args, session):
3467
3468 """
3469 Called by the network function. Prints out the DomainName.
3470
3471 @param host: string, the hostname or IP address of the bmc
3472 @param args: contains additional arguments used by the ldap subcommand
3473 args.json: boolean, if this flag is set to true, the output
3474 will be provided in json format for programmatic consumption
3475 @param session: the active session to use
3476 """
3477
3478 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3479 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003480
3481 try:
Justin Thaler27197622019-01-23 14:42:11 -06003482 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003483 except(requests.exceptions.Timeout):
3484 return(connectionErrHandler(args.json, "Timeout", None))
3485 except(requests.exceptions.ConnectionError) as err:
3486 return connectionErrHandler(args.json, "ConnectionError", err)
3487 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003488 return "The DomainName is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003489
3490 return res.text
3491
3492
3493def setDomainName(host, args, session):
3494 """
3495 Called by the network function. Sets the DomainName.
3496
3497 @param host: string, the hostname or IP address of the bmc
3498 @param args: contains additional arguments used by the ldap subcommand
3499 args.json: boolean, if this flag is set to true, the output
3500 will be provided in json format for programmatic consumption
3501 @param session: the active session to use
3502 """
3503
3504 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3505 "/attr/DomainName"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003506
3507 data = {"data": args.DomainName.split(",")}
3508
3509 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003510 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003511 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003512 except(requests.exceptions.Timeout):
3513 return(connectionErrHandler(args.json, "Timeout", None))
3514 except(requests.exceptions.ConnectionError) as err:
3515 return connectionErrHandler(args.json, "ConnectionError", err)
3516 if res.status_code == 403:
3517 return "The specified Interface"+"("+args.Interface+")"+\
3518 " doesn't exist"
3519
3520 return res.text
3521
3522
3523def getMACAddress(host, args, session):
3524
3525 """
3526 Called by the network function. Prints out the MACAddress.
3527
3528 @param host: string, the hostname or IP address of the bmc
3529 @param args: contains additional arguments used by the ldap subcommand
3530 args.json: boolean, if this flag is set to true, the output
3531 will be provided in json format for programmatic consumption
3532 @param session: the active session to use
3533 """
3534
3535 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3536 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003537
3538 try:
Justin Thaler27197622019-01-23 14:42:11 -06003539 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003540 except(requests.exceptions.Timeout):
3541 return(connectionErrHandler(args.json, "Timeout", None))
3542 except(requests.exceptions.ConnectionError) as err:
3543 return connectionErrHandler(args.json, "ConnectionError", err)
3544 if res.status_code == 404:
3545 return "The specified Interface"+"("+args.Interface+")"+\
3546 " doesn't exist"
3547
3548 return res.text
3549
3550
3551def setMACAddress(host, args, session):
3552 """
3553 Called by the network function. Sets the MACAddress.
3554
3555 @param host: string, the hostname or IP address of the bmc
3556 @param args: contains additional arguments used by the ldap subcommand
3557 args.json: boolean, if this flag is set to true, the output
3558 will be provided in json format for programmatic consumption
3559 @param session: the active session to use
3560 """
3561
3562 url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
3563 "/attr/MACAddress"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003564
3565 data = {"data": args.MACAddress}
3566
3567 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003568 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003569 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003570 except(requests.exceptions.Timeout):
3571 return(connectionErrHandler(args.json, "Timeout", None))
3572 except(requests.exceptions.ConnectionError) as err:
3573 return connectionErrHandler(args.json, "ConnectionError", err)
3574 if res.status_code == 403:
3575 return "The specified Interface"+"("+args.Interface+")"+\
3576 " doesn't exist"
3577
3578 return res.text
3579
3580
3581def getDefaultGateway(host, args, session):
3582
3583 """
3584 Called by the network function. Prints out the DefaultGateway.
3585
3586 @param host: string, the hostname or IP address of the bmc
3587 @param args: contains additional arguments used by the ldap subcommand
3588 args.json: boolean, if this flag is set to true, the output
3589 will be provided in json format for programmatic consumption
3590 @param session: the active session to use
3591 """
3592
3593 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003594
3595 try:
Justin Thaler27197622019-01-23 14:42:11 -06003596 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003597 except(requests.exceptions.Timeout):
3598 return(connectionErrHandler(args.json, "Timeout", None))
3599 except(requests.exceptions.ConnectionError) as err:
3600 return connectionErrHandler(args.json, "ConnectionError", err)
3601 if res.status_code == 404:
3602 return "Failed to get Default Gateway info!!"
3603
3604 return res.text
3605
3606
3607def setDefaultGateway(host, args, session):
3608 """
3609 Called by the network function. Sets the DefaultGateway.
3610
3611 @param host: string, the hostname or IP address of the bmc
3612 @param args: contains additional arguments used by the ldap subcommand
3613 args.json: boolean, if this flag is set to true, the output
3614 will be provided in json format for programmatic consumption
3615 @param session: the active session to use
3616 """
3617
3618 url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003619
3620 data = {"data": args.DefaultGW}
3621
3622 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003623 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003624 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003625 except(requests.exceptions.Timeout):
3626 return(connectionErrHandler(args.json, "Timeout", None))
3627 except(requests.exceptions.ConnectionError) as err:
3628 return connectionErrHandler(args.json, "ConnectionError", err)
3629 if res.status_code == 403:
3630 return "Failed to set Default Gateway!!"
3631
3632 return res.text
3633
3634
3635def viewNWConfig(host, args, session):
3636 """
3637 Called by the ldap function. Prints out network configured properties
3638
3639 @param host: string, the hostname or IP address of the bmc
3640 @param args: contains additional arguments used by the ldap subcommand
3641 args.json: boolean, if this flag is set to true, the output
3642 will be provided in json format for programmatic consumption
3643 @param session: the active session to use
3644 @return returns LDAP's configured properties.
3645 """
3646 url = "https://"+host+"/xyz/openbmc_project/network/enumerate"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003647 try:
Justin Thaler27197622019-01-23 14:42:11 -06003648 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003649 except(requests.exceptions.Timeout):
3650 return(connectionErrHandler(args.json, "Timeout", None))
3651 except(requests.exceptions.ConnectionError) as err:
3652 return connectionErrHandler(args.json, "ConnectionError", err)
3653 except(requests.exceptions.RequestException) as err:
3654 return connectionErrHandler(args.json, "RequestException", err)
3655 if res.status_code == 404:
3656 return "LDAP server config has not been created"
3657 return res.text
3658
3659
3660def getDNS(host, args, session):
3661
3662 """
3663 Called by the network function. Prints out DNS servers on the interface
3664
3665 @param host: string, the hostname or IP address of the bmc
3666 @param args: contains additional arguments used by the ldap subcommand
3667 args.json: boolean, if this flag is set to true, the output
3668 will be provided in json format for programmatic consumption
3669 @param session: the active session to use
3670 """
3671
3672 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3673 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003674
3675 try:
Justin Thaler27197622019-01-23 14:42:11 -06003676 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003677 except(requests.exceptions.Timeout):
3678 return(connectionErrHandler(args.json, "Timeout", None))
3679 except(requests.exceptions.ConnectionError) as err:
3680 return connectionErrHandler(args.json, "ConnectionError", err)
3681 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003682 return "The NameServer is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003683
3684 return res.text
3685
3686
3687def setDNS(host, args, session):
3688 """
3689 Called by the network function. Sets DNS servers on the interface.
3690
3691 @param host: string, the hostname or IP address of the bmc
3692 @param args: contains additional arguments used by the ldap subcommand
3693 args.json: boolean, if this flag is set to true, the output
3694 will be provided in json format for programmatic consumption
3695 @param session: the active session to use
3696 """
3697
3698 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3699 + "/attr/Nameservers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003700
3701 data = {"data": args.DNSServers.split(",")}
3702
3703 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003704 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003705 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003706 except(requests.exceptions.Timeout):
3707 return(connectionErrHandler(args.json, "Timeout", None))
3708 except(requests.exceptions.ConnectionError) as err:
3709 return connectionErrHandler(args.json, "ConnectionError", err)
3710 if res.status_code == 403:
3711 return "The specified Interface"+"("+args.Interface+")" +\
3712 " doesn't exist"
3713
3714 return res.text
3715
3716
3717def getNTP(host, args, session):
3718
3719 """
3720 Called by the network function. Prints out NTP servers on the interface
3721
3722 @param host: string, the hostname or IP address of the bmc
3723 @param args: contains additional arguments used by the ldap subcommand
3724 args.json: boolean, if this flag is set to true, the output
3725 will be provided in json format for programmatic consumption
3726 @param session: the active session to use
3727 """
3728
3729 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3730 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003731 try:
Justin Thaler27197622019-01-23 14:42:11 -06003732 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003733 except(requests.exceptions.Timeout):
3734 return(connectionErrHandler(args.json, "Timeout", None))
3735 except(requests.exceptions.ConnectionError) as err:
3736 return connectionErrHandler(args.json, "ConnectionError", err)
3737 if res.status_code == 404:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003738 return "The NTPServer is not configured on Interface"+"("+args.Interface+")"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003739
3740 return res.text
3741
3742
3743def setNTP(host, args, session):
3744 """
3745 Called by the network function. Sets NTP servers on the interface.
3746
3747 @param host: string, the hostname or IP address of the bmc
3748 @param args: contains additional arguments used by the ldap subcommand
3749 args.json: boolean, if this flag is set to true, the output
3750 will be provided in json format for programmatic consumption
3751 @param session: the active session to use
3752 """
3753
3754 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3755 + "/attr/NTPServers"
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003756
3757 data = {"data": args.NTPServers.split(",")}
3758
3759 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003760 res = session.put(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003761 timeout=baseTimeout)
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06003762 except(requests.exceptions.Timeout):
3763 return(connectionErrHandler(args.json, "Timeout", None))
3764 except(requests.exceptions.ConnectionError) as err:
3765 return connectionErrHandler(args.json, "ConnectionError", err)
3766 if res.status_code == 403:
3767 return "The specified Interface"+"("+args.Interface+")" +\
3768 " doesn't exist"
3769
3770 return res.text
3771
3772
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003773def addIP(host, args, session):
3774 """
3775 Called by the network function. Configures IP address on given interface
3776
3777 @param host: string, the hostname or IP address of the bmc
3778 @param args: contains additional arguments used by the ldap subcommand
3779 args.json: boolean, if this flag is set to true, the output
3780 will be provided in json format for programmatic consumption
3781 @param session: the active session to use
3782 """
3783
3784 url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
3785 + "/action/IP"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003786 protocol = {
3787 'ipv4': 'xyz.openbmc_project.Network.IP.Protocol.IPv4',
3788 'ipv6': 'xyz.openbmc_project.Network.IP.Protocol.IPv6'
3789 }
3790
3791 data = {"data": [protocol[args.type], args.address, int(args.prefixLength),
3792 args.gateway]}
3793
3794 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003795 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003796 timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003797 except(requests.exceptions.Timeout):
3798 return(connectionErrHandler(args.json, "Timeout", None))
3799 except(requests.exceptions.ConnectionError) as err:
3800 return connectionErrHandler(args.json, "ConnectionError", err)
3801 if res.status_code == 404:
3802 return "The specified Interface" + "(" + args.Interface + ")" +\
3803 " doesn't exist"
3804
3805 return res.text
3806
3807
3808def getIP(host, args, session):
3809 """
3810 Called by the network function. Prints out IP address of given interface
3811
3812 @param host: string, the hostname or IP address of the bmc
3813 @param args: contains additional arguments used by the ldap subcommand
3814 args.json: boolean, if this flag is set to true, the output
3815 will be provided in json format for programmatic consumption
3816 @param session: the active session to use
3817 """
3818
3819 url = "https://" + host+"/xyz/openbmc_project/network/" + args.Interface +\
3820 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003821 try:
Justin Thaler27197622019-01-23 14:42:11 -06003822 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003823 except(requests.exceptions.Timeout):
3824 return(connectionErrHandler(args.json, "Timeout", None))
3825 except(requests.exceptions.ConnectionError) as err:
3826 return connectionErrHandler(args.json, "ConnectionError", err)
3827 if res.status_code == 404:
3828 return "The specified Interface" + "(" + args.Interface + ")" +\
3829 " doesn't exist"
3830
3831 return res.text
3832
3833
3834def deleteIP(host, args, session):
3835 """
3836 Called by the network function. Deletes the IP address from given Interface
3837
3838 @param host: string, the hostname or IP address of the bmc
3839 @param args: contains additional arguments used by the ldap subcommand
3840 @param session: the active session to use
3841 @param args.json: boolean, if this flag is set to true, the output
3842 will be provided in json format for programmatic consumption
3843 """
3844
3845 url = "https://"+host+"/xyz/openbmc_project/network/" + args.Interface+\
3846 "/enumerate"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003847 data = {"data": []}
3848 try:
Justin Thaler27197622019-01-23 14:42:11 -06003849 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003850 except(requests.exceptions.Timeout):
3851 return(connectionErrHandler(args.json, "Timeout", None))
3852 except(requests.exceptions.ConnectionError) as err:
3853 return connectionErrHandler(args.json, "ConnectionError", err)
3854 if res.status_code == 404:
3855 return "The specified Interface" + "(" + args.Interface + ")" +\
3856 " doesn't exist"
3857 objDict = json.loads(res.text)
3858 if not objDict['data']:
3859 return "No object found for given address on given Interface"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003860 for obj in objDict['data']:
Sunitha Harish0baf6372019-07-31 03:59:03 -05003861 try:
3862 if args.address in objDict['data'][obj]['Address']:
3863 url = "https://"+host+obj+"/action/Delete"
3864 try:
3865 res = session.post(url, headers=jsonHeader, json=data,
3866 verify=False, timeout=baseTimeout)
3867 except(requests.exceptions.Timeout):
3868 return(connectionErrHandler(args.json, "Timeout", None))
3869 except(requests.exceptions.ConnectionError) as err:
3870 return connectionErrHandler(args.json, "ConnectionError", err)
3871 return res.text
3872 else:
3873 continue
3874 except KeyError:
Sunitha Harishf9bb2fa2019-09-19 01:48:00 -05003875 continue
3876 return "No object found for address " + args.address + \
3877 " on Interface(" + args.Interface + ")"
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06003878
3879
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003880def addVLAN(host, args, session):
3881 """
3882 Called by the network function. Creates VLAN on given interface.
3883
3884 @param host: string, the hostname or IP address of the bmc
3885 @param args: contains additional arguments used by the ldap subcommand
3886 args.json: boolean, if this flag is set to true, the output
3887 will be provided in json format for programmatic consumption
3888 @param session: the active session to use
3889 """
3890
3891 url = "https://" + host+"/xyz/openbmc_project/network/action/VLAN"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003892
Sunitha Harish0baf6372019-07-31 03:59:03 -05003893 data = {"data": [args.Interface,int(args.Identifier)]}
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003894 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06003895 res = session.post(url, headers=jsonHeader, json=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06003896 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003897 except(requests.exceptions.Timeout):
3898 return(connectionErrHandler(args.json, "Timeout", None))
3899 except(requests.exceptions.ConnectionError) as err:
3900 return connectionErrHandler(args.json, "ConnectionError", err)
3901 if res.status_code == 400:
Sunitha Harish0baf6372019-07-31 03:59:03 -05003902 return "Adding VLAN to interface" + "(" + args.Interface + ")" +\
3903 " failed"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003904
3905 return res.text
3906
3907
3908def deleteVLAN(host, args, session):
3909 """
3910 Called by the network function. Creates VLAN on given interface.
3911
3912 @param host: string, the hostname or IP address of the bmc
3913 @param args: contains additional arguments used by the ldap subcommand
3914 args.json: boolean, if this flag is set to true, the output
3915 will be provided in json format for programmatic consumption
3916 @param session: the active session to use
3917 """
3918
Sunitha Harish577a5032019-08-08 06:27:40 -05003919 url = "https://" + host+"/xyz/openbmc_project/network/"+args.Interface+"/action/Delete"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003920 data = {"data": []}
3921
3922 try:
Justin Thaler27197622019-01-23 14:42:11 -06003923 res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003924 except(requests.exceptions.Timeout):
3925 return(connectionErrHandler(args.json, "Timeout", None))
3926 except(requests.exceptions.ConnectionError) as err:
3927 return connectionErrHandler(args.json, "ConnectionError", err)
3928 if res.status_code == 404:
Sunitha Harish577a5032019-08-08 06:27:40 -05003929 return "The specified VLAN"+"("+args.Interface+")" +" doesn't exist"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003930
3931 return res.text
3932
3933
3934def viewDHCPConfig(host, args, session):
3935 """
3936 Called by the network function. Shows DHCP configured Properties.
3937
3938 @param host: string, the hostname or IP address of the bmc
3939 @param args: contains additional arguments used by the ldap subcommand
3940 args.json: boolean, if this flag is set to true, the output
3941 will be provided in json format for programmatic consumption
3942 @param session: the active session to use
3943 """
3944
3945 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003946
3947 try:
Justin Thaler27197622019-01-23 14:42:11 -06003948 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003949 except(requests.exceptions.Timeout):
3950 return(connectionErrHandler(args.json, "Timeout", None))
3951 except(requests.exceptions.ConnectionError) as err:
3952 return connectionErrHandler(args.json, "ConnectionError", err)
3953
3954 return res.text
3955
3956
3957def configureDHCP(host, args, session):
3958 """
3959 Called by the network function. Configures/updates DHCP Properties.
3960
3961 @param host: string, the hostname or IP address of the bmc
3962 @param args: contains additional arguments used by the ldap subcommand
3963 args.json: boolean, if this flag is set to true, the output
3964 will be provided in json format for programmatic consumption
3965 @param session: the active session to use
3966 """
3967
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003968
3969 try:
3970 url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
3971 if(args.DNSEnabled == True):
3972 data = '{"data": 1}'
3973 else:
3974 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06003975 res = session.put(url + '/attr/DNSEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06003976 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003977 if(args.HostNameEnabled == True):
3978 data = '{"data": 1}'
3979 else:
3980 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06003981 res = session.put(url + '/attr/HostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06003982 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003983 if(args.NTPEnabled == True):
3984 data = '{"data": 1}'
3985 else:
3986 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06003987 res = session.put(url + '/attr/NTPEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06003988 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003989 if(args.SendHostNameEnabled == True):
3990 data = '{"data": 1}'
3991 else:
3992 data = '{"data": 0}'
Matt Spinler220c3c42019-01-04 15:09:29 -06003993 res = session.put(url + '/attr/SendHostNameEnabled', headers=jsonHeader,
Justin Thaler27197622019-01-23 14:42:11 -06003994 data=data, verify=False, timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06003995 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
4000 return res.text
4001
4002
4003def nwReset(host, args, session):
4004
4005 """
4006 Called by the network function. Resets networks setting to factory defaults.
4007
4008 @param host: string, the hostname or IP address of the bmc
4009 @param args: contains additional arguments used by the ldap subcommand
4010 args.json: boolean, if this flag is set to true, the output
4011 will be provided in json format for programmatic consumption
4012 @param session: the active session to use
4013 """
4014
4015 url = "https://"+host+"/xyz/openbmc_project/network/action/Reset"
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004016 data = '{"data":[] }'
4017 try:
Matt Spinler220c3c42019-01-04 15:09:29 -06004018 res = session.post(url, headers=jsonHeader, data=data, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004019 timeout=baseTimeout)
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004020
4021 except(requests.exceptions.Timeout):
4022 return(connectionErrHandler(args.json, "Timeout", None))
4023 except(requests.exceptions.ConnectionError) as err:
4024 return connectionErrHandler(args.json, "ConnectionError", err)
4025
4026 return res.text
4027
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004028def getLDAPTypeEnabled(host,session):
4029
4030 """
4031 Called by LDAP related functions to find the LDAP server type that has been enabled.
4032 Returns None if LDAP has not been configured.
4033
4034 @param host: string, the hostname or IP address of the bmc
4035 @param session: the active session to use
4036 """
4037
4038 enabled = False
4039 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
4040 for key,value in serverTypeMap.items():
4041 data = {"data": []}
4042 try:
4043 res = session.get(url + value + '/attr/Enabled', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4044 except(requests.exceptions.Timeout):
4045 print(connectionErrHandler(args.json, "Timeout", None))
4046 return
4047 except(requests.exceptions.ConnectionError) as err:
4048 print(connectionErrHandler(args.json, "ConnectionError", err))
4049 return
4050
4051 enabled = res.json()['data']
4052 if (enabled):
4053 return key
4054
4055def syncRoleMap(host,args,session,fromServerType,toServerType):
4056
4057 """
4058 Called by LDAP related functions to sync the role maps
4059 Returns False if LDAP has not been configured.
4060
4061 @param host: string, the hostname or IP address of the bmc
4062 @param session: the active session to use
4063 @param fromServerType : Server type whose role map has to be copied
4064 @param toServerType : Server type to which role map has to be copied
4065 """
4066
4067 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
4068
4069 try:
4070 #Note: If the fromServerType has no role map, then
4071 #the toServerType will not have any role map.
4072
4073 #delete the privilege mapping from the toServerType and
4074 #then copy the privilege mapping from fromServerType to
4075 #toServerType.
4076 args.serverType = toServerType
4077 res = deleteAllPrivilegeMapping(host, args, session)
4078
4079 data = {"data": []}
4080 res = session.get(url + serverTypeMap[fromServerType] + '/role_map/enumerate', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4081 #Previously enabled server type has no role map
4082 if (res.status_code != requests.codes.ok):
4083
4084 #fromServerType has no role map; So, no need to copy
4085 #role map to toServerType.
4086 return
4087
4088 objDict = json.loads(res.text)
4089 dataDict = objDict['data']
4090 for key,value in dataDict.items():
4091 data = {"data": [value["GroupName"], value["Privilege"]]}
4092 res = session.post(url + serverTypeMap[toServerType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4093
4094 except(requests.exceptions.Timeout):
4095 return(connectionErrHandler(args.json, "Timeout", None))
4096 except(requests.exceptions.ConnectionError) as err:
4097 return connectionErrHandler(args.json, "ConnectionError", err)
4098 return res.text
4099
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004100
Ratan Guptafeee6372018-10-17 23:25:51 +05304101def createPrivilegeMapping(host, args, session):
4102 """
4103 Called by the ldap function. Creates the group and the privilege mapping.
4104
4105 @param host: string, the hostname or IP address of the bmc
4106 @param args: contains additional arguments used by the ldap subcommand
4107 @param session: the active session to use
4108 @param args.json: boolean, if this flag is set to true, the output
4109 will be provided in json format for programmatic consumption
4110 """
4111
Ratan Guptafeee6372018-10-17 23:25:51 +05304112 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004113 if (isRedfishSupport):
4114 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
4115
4116 #To maintain the interface compatibility between op930 and op940, the server type has been made
4117 #optional. If the server type is not specified, then create the role-mapper for the currently
4118 #enabled server type.
4119 serverType = args.serverType
4120 if (serverType is None):
4121 serverType = getLDAPTypeEnabled(host,session)
4122 if (serverType is None):
4123 return("LDAP server has not been enabled. Please specify LDAP serverType to proceed further...")
4124
4125 data = {"data": [args.groupName,args.privilege]}
4126 res = session.post(url + serverTypeMap[serverType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4127
4128 else:
4129 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/action/Create'
4130 data = {"data": [args.groupName,args.privilege]}
4131 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
4132
Ratan Guptafeee6372018-10-17 23:25:51 +05304133 except(requests.exceptions.Timeout):
4134 return(connectionErrHandler(args.json, "Timeout", None))
4135 except(requests.exceptions.ConnectionError) as err:
4136 return connectionErrHandler(args.json, "ConnectionError", err)
4137 return res.text
4138
4139def listPrivilegeMapping(host, args, session):
4140 """
4141 Called by the ldap function. Lists the group and the privilege mapping.
4142
4143 @param host: string, the hostname or IP address of the bmc
4144 @param args: contains additional arguments used by the ldap subcommand
4145 @param session: the active session to use
4146 @param args.json: boolean, if this flag is set to true, the output
4147 will be provided in json format for programmatic consumption
4148 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004149
4150 if (isRedfishSupport):
4151 serverType = args.serverType
4152 if (serverType is None):
4153 serverType = getLDAPTypeEnabled(host,session)
4154 if (serverType is None):
4155 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4156
4157 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'+serverTypeMap[serverType]+'/role_map/enumerate'
4158
4159 else:
4160 url = 'https://'+host+'/xyz/openbmc_project/user/ldap/enumerate'
4161
Ratan Guptafeee6372018-10-17 23:25:51 +05304162 data = {"data": []}
4163
4164 try:
Justin Thaler27197622019-01-23 14:42:11 -06004165 res = session.get(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05304166 except(requests.exceptions.Timeout):
4167 return(connectionErrHandler(args.json, "Timeout", None))
4168 except(requests.exceptions.ConnectionError) as err:
4169 return connectionErrHandler(args.json, "ConnectionError", err)
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004170
Ratan Guptafeee6372018-10-17 23:25:51 +05304171 return res.text
4172
4173def deletePrivilegeMapping(host, args, session):
4174 """
4175 Called by the ldap function. Deletes the mapping associated with the group.
4176
4177 @param host: string, the hostname or IP address of the bmc
4178 @param args: contains additional arguments used by the ldap subcommand
4179 @param session: the active session to use
4180 @param args.json: boolean, if this flag is set to true, the output
4181 will be provided in json format for programmatic consumption
4182 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004183
4184 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
Ratan Guptafeee6372018-10-17 23:25:51 +05304185 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
4186 path = ''
Ratan Guptafeee6372018-10-17 23:25:51 +05304187 data = {"data": []}
4188
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004189 if (isRedfishSupport):
4190 if (args.serverType is None):
4191 serverType = getLDAPTypeEnabled(host,session)
4192 if (serverType is None):
4193 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4194 # search for the object having the mapping for the given group
4195 for key,value in ldapNameSpaceObjects.items():
4196 if value['GroupName'] == args.groupName:
4197 path = key
4198 break
4199
4200 if path == '':
4201 return "No privilege mapping found for this group."
4202
4203 # delete the object
4204 url = 'https://'+host+path+'/action/Delete'
4205
4206 else:
4207 # not interested in the config objet
4208 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
4209
4210 # search for the object having the mapping for the given group
4211 for key,value in ldapNameSpaceObjects.items():
4212 if value['GroupName'] == args.groupName:
4213 path = key
4214 break
4215
4216 if path == '':
4217 return "No privilege mapping found for this group."
4218
4219 # delete the object
4220 url = 'https://'+host+path+'/action/delete'
4221
Ratan Guptafeee6372018-10-17 23:25:51 +05304222 try:
Justin Thaler27197622019-01-23 14:42:11 -06004223 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
Ratan Guptafeee6372018-10-17 23:25:51 +05304224 except(requests.exceptions.Timeout):
4225 return(connectionErrHandler(args.json, "Timeout", None))
4226 except(requests.exceptions.ConnectionError) as err:
4227 return connectionErrHandler(args.json, "ConnectionError", err)
4228 return res.text
Ratan Gupta9166cd22018-10-01 18:09:40 +05304229
Sivas SRR78835272018-11-27 05:27:19 -06004230def deleteAllPrivilegeMapping(host, args, session):
4231 """
4232 Called by the ldap function. Deletes all the privilege mapping and group defined.
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 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004239
Sivas SRR78835272018-11-27 05:27:19 -06004240 ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
4241 ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
4242 path = ''
Sivas SRR78835272018-11-27 05:27:19 -06004243 data = {"data": []}
4244
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004245 if (isRedfishSupport):
4246 if (args.serverType is None):
4247 serverType = getLDAPTypeEnabled(host,session)
4248 if (serverType is None):
4249 return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
4250
4251 else:
4252 # Remove the config object.
4253 ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
4254
Sivas SRR78835272018-11-27 05:27:19 -06004255 try:
4256 # search for GroupName property and delete if it is available.
4257 for path in ldapNameSpaceObjects.keys():
4258 # delete the object
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004259 url = 'https://'+host+path+'/action/Delete'
Justin Thaler27197622019-01-23 14:42:11 -06004260 res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004261
Sivas SRR78835272018-11-27 05:27:19 -06004262 except(requests.exceptions.Timeout):
4263 return(connectionErrHandler(args.json, "Timeout", None))
4264 except(requests.exceptions.ConnectionError) as err:
4265 return connectionErrHandler(args.json, "ConnectionError", err)
4266 return res.text
4267
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004268def viewLDAPConfig(host, args, session):
4269 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004270 Called by the ldap function. Prints out active LDAP configuration properties
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004271
4272 @param host: string, the hostname or IP address of the bmc
4273 @param args: contains additional arguments used by the ldap subcommand
4274 args.json: boolean, if this flag is set to true, the output
4275 will be provided in json format for programmatic consumption
4276 @param session: the active session to use
4277 @return returns LDAP's configured properties.
4278 """
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004279
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004280 try:
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004281 if (isRedfishSupport):
4282
4283 url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
4284
4285 serverTypeEnabled = getLDAPTypeEnabled(host,session)
4286
4287 if (serverTypeEnabled is not None):
4288 data = {"data": []}
4289 res = session.get(url + serverTypeMap[serverTypeEnabled], headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
4290 else:
4291 return("LDAP server has not been enabled...")
4292
4293 else :
4294 url = "https://"+host+"/xyz/openbmc_project/user/ldap/config"
4295 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
4296
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004297 except(requests.exceptions.Timeout):
4298 return(connectionErrHandler(args.json, "Timeout", None))
4299 except(requests.exceptions.ConnectionError) as err:
4300 return connectionErrHandler(args.json, "ConnectionError", err)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004301 if res.status_code == 404:
4302 return "LDAP server config has not been created"
4303 return res.text
4304
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06004305def str2bool(v):
4306 if v.lower() in ('yes', 'true', 't', 'y', '1'):
4307 return True
4308 elif v.lower() in ('no', 'false', 'f', 'n', '0'):
4309 return False
4310 else:
4311 raise argparse.ArgumentTypeError('Boolean value expected.')
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004312
Matt Spinler7d426c22018-09-24 14:42:07 -05004313def localUsers(host, args, session):
4314 """
4315 Enables and disables local BMC users.
4316
4317 @param host: string, the hostname or IP address of the bmc
4318 @param args: contains additional arguments used by the logging sub command
4319 @param session: the active session to use
4320 """
4321
Matt Spinler7d426c22018-09-24 14:42:07 -05004322 url="https://{hostname}/xyz/openbmc_project/user/enumerate".format(hostname=host)
4323 try:
Justin Thaler27197622019-01-23 14:42:11 -06004324 res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004325 except(requests.exceptions.Timeout):
4326 return(connectionErrHandler(args.json, "Timeout", None))
4327 usersDict = json.loads(res.text)
4328
4329 if not usersDict['data']:
4330 return "No users found"
4331
4332 output = ""
4333 for user in usersDict['data']:
Matt Spinler015adc22018-10-23 14:30:19 -05004334
4335 # Skip LDAP and another non-local users
4336 if 'UserEnabled' not in usersDict['data'][user]:
4337 continue
4338
Matt Spinler7d426c22018-09-24 14:42:07 -05004339 name = user.split('/')[-1]
4340 url = "https://{hostname}{user}/attr/UserEnabled".format(hostname=host, user=user)
4341
4342 if args.local_users == "queryenabled":
4343 try:
Justin Thaler27197622019-01-23 14:42:11 -06004344 res = session.get(url, headers=jsonHeader,verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004345 except(requests.exceptions.Timeout):
4346 return(connectionErrHandler(args.json, "Timeout", None))
4347
4348 result = json.loads(res.text)
4349 output += ("User: {name} Enabled: {result}\n").format(name=name, result=result['data'])
4350
4351 elif args.local_users in ["enableall", "disableall"]:
4352 action = ""
4353 if args.local_users == "enableall":
4354 data = '{"data": true}'
4355 action = "Enabling"
4356 else:
4357 data = '{"data": false}'
4358 action = "Disabling"
4359
4360 output += "{action} {name}\n".format(action=action, name=name)
4361
4362 try:
Justin Thaler27197622019-01-23 14:42:11 -06004363 resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
Matt Spinler7d426c22018-09-24 14:42:07 -05004364 except(requests.exceptions.Timeout):
4365 return connectionErrHandler(args.json, "Timeout", None)
4366 except(requests.exceptions.ConnectionError) as err:
4367 return connectionErrHandler(args.json, "ConnectionError", err)
4368 else:
4369 return "Invalid local users argument"
4370
4371 return output
4372
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004373def setPassword(host, args, session):
4374 """
4375 Set local user password
4376 @param host: string, the hostname or IP address of the bmc
4377 @param args: contains additional arguments used by the logging sub
4378 command
4379 @param session: the active session to use
4380 @param args.json: boolean, if this flag is set to true, the output
4381 will be provided in json format for programmatic consumption
4382 @return: Session object
4383 """
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004384 try:
Sunitha Harishc99faba2019-07-19 06:55:22 -05004385 if(isRedfishSupport):
4386 url = "https://" + host + "/redfish/v1/AccountService/Accounts/"+ \
4387 args.user
4388 data = {"Password":args.password}
4389 res = session.patch(url, headers=jsonHeader, json=data,
4390 verify=False, timeout=baseTimeout)
4391 else:
4392 url = "https://" + host + "/xyz/openbmc_project/user/" + args.user + \
4393 "/action/SetPassword"
4394 res = session.post(url, headers=jsonHeader,
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004395 json={"data": [args.password]}, verify=False,
Justin Thaler27197622019-01-23 14:42:11 -06004396 timeout=baseTimeout)
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004397 except(requests.exceptions.Timeout):
4398 return(connectionErrHandler(args.json, "Timeout", None))
4399 except(requests.exceptions.ConnectionError) as err:
4400 return connectionErrHandler(args.json, "ConnectionError", err)
4401 except(requests.exceptions.RequestException) as err:
4402 return connectionErrHandler(args.json, "RequestException", err)
Sunitha Harishc99faba2019-07-19 06:55:22 -05004403 return res.status_code
Matthew Barth368e83c2019-02-01 13:48:25 -06004404
4405def getThermalZones(host, args, session):
4406 """
4407 Get the available thermal control zones
4408 @param host: string, the hostname or IP address of the bmc
4409 @param args: contains additional arguments used to get the thermal
4410 control zones
4411 @param session: the active session to use
4412 @return: Session object
4413 """
4414 url = "https://" + host + "/xyz/openbmc_project/control/thermal/enumerate"
4415
4416 try:
4417 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4418 except(requests.exceptions.Timeout):
4419 return(connectionErrHandler(args.json, "Timeout", None))
4420 except(requests.exceptions.ConnectionError) as err:
4421 return connectionErrHandler(args.json, "ConnectionError", err)
4422 except(requests.exceptions.RequestException) as err:
4423 return connectionErrHandler(args.json, "RequestException", err)
4424
4425 if (res.status_code == 404):
Matthew Barth0939e822019-09-27 15:47:50 -05004426 return "No thermal control zones found"
Matthew Barth368e83c2019-02-01 13:48:25 -06004427
4428 zonesDict = json.loads(res.text)
4429 if not zonesDict['data']:
4430 return "No thermal control zones found"
4431 for zone in zonesDict['data']:
4432 z = ",".join(str(zone.split('/')[-1]) for zone in zonesDict['data'])
4433
4434 return "Zones: [ " + z + " ]"
4435
4436
4437def getThermalMode(host, args, session):
4438 """
4439 Get thermal control mode
4440 @param host: string, the hostname or IP address of the bmc
4441 @param args: contains additional arguments used to get the thermal
4442 control mode
4443 @param session: the active session to use
4444 @param args.zone: the zone to get the mode on
4445 @return: Session object
4446 """
4447 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
4448 args.zone
4449
4450 try:
4451 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4452 except(requests.exceptions.Timeout):
4453 return(connectionErrHandler(args.json, "Timeout", None))
4454 except(requests.exceptions.ConnectionError) as err:
4455 return connectionErrHandler(args.json, "ConnectionError", err)
4456 except(requests.exceptions.RequestException) as err:
4457 return connectionErrHandler(args.json, "RequestException", err)
4458
4459 if (res.status_code == 404):
Matthew Barth0939e822019-09-27 15:47:50 -05004460 return "Thermal control zone(" + args.zone + ") not found"
Matthew Barth368e83c2019-02-01 13:48:25 -06004461
4462 propsDict = json.loads(res.text)
4463 if not propsDict['data']:
4464 return "No thermal control properties found on zone(" + args.zone + ")"
4465 curMode = "Current"
4466 supModes = "Supported"
4467 result = "\n"
4468 for prop in propsDict['data']:
4469 if (prop.casefold() == curMode.casefold()):
4470 result += curMode + " Mode: " + propsDict['data'][curMode] + "\n"
4471 if (prop.casefold() == supModes.casefold()):
4472 s = ", ".join(str(sup) for sup in propsDict['data'][supModes])
4473 result += supModes + " Modes: [ " + s + " ]\n"
4474
4475 return result
4476
4477def setThermalMode(host, args, session):
4478 """
4479 Set thermal control mode
4480 @param host: string, the hostname or IP address of the bmc
4481 @param args: contains additional arguments used for setting the thermal
4482 control mode
4483 @param session: the active session to use
4484 @param args.zone: the zone to set the mode on
4485 @param args.mode: the mode to enable
4486 @return: Session object
4487 """
4488 url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
4489 args.zone + "/attr/Current"
4490
4491 # Check args.mode against supported modes using `getThermalMode` output
4492 modes = getThermalMode(host, args, session)
4493 modes = os.linesep.join([m for m in modes.splitlines() if m])
4494 modes = modes.replace("\n", ";").strip()
4495 modesDict = dict(m.split(': ') for m in modes.split(';'))
4496 sModes = ''.join(s for s in modesDict['Supported Modes'] if s not in '[ ]')
4497 if args.mode.casefold() not in \
4498 (m.casefold() for m in sModes.split(',')) or not args.mode:
4499 result = ("Unsupported mode('" + args.mode + "') given, " +
4500 "select a supported mode: \n" +
4501 getThermalMode(host, args, session))
4502 return result
4503
4504 data = '{"data":"' + args.mode + '"}'
4505 try:
4506 res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
4507 except(requests.exceptions.Timeout):
4508 return(connectionErrHandler(args.json, "Timeout", None))
4509 except(requests.exceptions.ConnectionError) as err:
4510 return connectionErrHandler(args.json, "ConnectionError", err)
4511 except(requests.exceptions.RequestException) as err:
4512 return connectionErrHandler(args.json, "RequestException", err)
4513
4514 if (data and res.status_code != 404):
4515 try:
4516 res = session.put(url, headers=jsonHeader,
4517 data=data, verify=False,
4518 timeout=30)
4519 except(requests.exceptions.Timeout):
4520 return(connectionErrHandler(args.json, "Timeout", None))
4521 except(requests.exceptions.ConnectionError) as err:
4522 return connectionErrHandler(args.json, "ConnectionError", err)
4523 except(requests.exceptions.RequestException) as err:
4524 return connectionErrHandler(args.json, "RequestException", err)
4525
4526 if res.status_code == 403:
4527 return "The specified thermal control zone(" + args.zone + ")" + \
4528 " does not exist"
4529
4530 return res.text
4531 else:
4532 return "Setting thermal control mode(" + args.mode + ")" + \
Matthew Barth0939e822019-09-27 15:47:50 -05004533 " not supported or operation not available"
Matthew Barth368e83c2019-02-01 13:48:25 -06004534
4535
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004536def createCommandParser():
Justin Thalere412dc22018-01-12 16:28:24 -06004537 """
4538 creates the parser for the command line along with help for each command and subcommand
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004539
Justin Thalere412dc22018-01-12 16:28:24 -06004540 @return: returns the parser for the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004541 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004542 parser = argparse.ArgumentParser(description='Process arguments')
Justin Thalere412dc22018-01-12 16:28:24 -06004543 parser.add_argument("-H", "--host", help='A hostname or IP for the BMC')
4544 parser.add_argument("-U", "--user", help='The username to login with')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004545 group = parser.add_mutually_exclusive_group()
4546 group.add_argument("-A", "--askpw", action='store_true', help='prompt for password')
4547 group.add_argument("-P", "--PW", help='Provide the password in-line')
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05004548 group.add_argument("-E", "--PWenvvar", action='store_true', help='Get password from envvar OPENBMCTOOL_PASSWORD')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004549 parser.add_argument('-j', '--json', action='store_true', help='output json data only')
4550 parser.add_argument('-t', '--policyTableLoc', help='The location of the policy table to parse alerts')
4551 parser.add_argument('-c', '--CerFormat', action='store_true', help=argparse.SUPPRESS)
4552 parser.add_argument('-T', '--procTime', action='store_true', help= argparse.SUPPRESS)
Justin Thalere412dc22018-01-12 16:28:24 -06004553 parser.add_argument('-V', '--version', action='store_true', help='Display the version number of the openbmctool')
4554 subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004555
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004556 #fru command
4557 parser_inv = subparsers.add_parser("fru", help='Work with platform inventory')
Justin Thalere412dc22018-01-12 16:28:24 -06004558 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 -05004559 inv_subparser.required = True
4560 #fru print
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004561 inv_print = inv_subparser.add_parser("print", help="prints out a list of all FRUs")
4562 inv_print.set_defaults(func=fruPrint)
4563 #fru list [0....n]
4564 inv_list = inv_subparser.add_parser("list", help="print out details on selected FRUs. Specifying no items will list the entire inventory")
4565 inv_list.add_argument('items', nargs='?', help="print out details on selected FRUs. Specifying no items will list the entire inventory")
4566 inv_list.set_defaults(func=fruList)
4567 #fru status
4568 inv_status = inv_subparser.add_parser("status", help="prints out the status of all FRUs")
Justin Thalere412dc22018-01-12 16:28:24 -06004569 inv_status.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004570 inv_status.set_defaults(func=fruStatus)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004571
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004572 #sensors command
4573 parser_sens = subparsers.add_parser("sensors", help="Work with platform sensors")
Justin Thalere412dc22018-01-12 16:28:24 -06004574 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 -05004575 sens_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004576 #sensor print
4577 sens_print= sens_subparser.add_parser('print', help="prints out a list of all Sensors.")
4578 sens_print.set_defaults(func=sensor)
4579 #sensor list[0...n]
4580 sens_list=sens_subparser.add_parser("list", help="Lists all Sensors in the platform. Specify a sensor for full details. ")
4581 sens_list.add_argument("sensNum", nargs='?', help="The Sensor number to get full details on" )
4582 sens_list.set_defaults(func=sensor)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004583
Matthew Barth368e83c2019-02-01 13:48:25 -06004584 #thermal control commands
4585 parser_therm = subparsers.add_parser("thermal", help="Work with thermal control parameters")
4586 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')
4587 #thermal control zones
4588 parser_thermZones = therm_subparser.add_parser("zones", help="Get a list of available thermal control zones")
4589 parser_thermZones.set_defaults(func=getThermalZones)
4590 #thermal control modes
4591 parser_thermMode = therm_subparser.add_parser("modes", help="Work with thermal control modes")
4592 thermMode_sub = parser_thermMode.add_subparsers(title='subactions', description='Work with thermal control modes', help="Work with thermal control modes")
4593 #get thermal control mode
4594 parser_getThermMode = thermMode_sub.add_parser("get", help="Get current and supported thermal control modes")
4595 parser_getThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
4596 parser_getThermMode.set_defaults(func=getThermalMode)
4597 #set thermal control mode
4598 parser_setThermMode = thermMode_sub.add_parser("set", help="Set the thermal control mode")
4599 parser_setThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
4600 parser_setThermMode.add_argument('-m', '--mode', required=True, help='The supported thermal control mode')
4601 parser_setThermMode.set_defaults(func=setThermalMode)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004602
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004603 #sel command
4604 parser_sel = subparsers.add_parser("sel", help="Work with platform alerts")
Justin Thalere412dc22018-01-12 16:28:24 -06004605 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 -05004606 sel_subparser.required = True
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004607 #sel print
4608 sel_print = sel_subparser.add_parser("print", help="prints out a list of all sels in a condensed list")
4609 sel_print.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
4610 sel_print.add_argument('-v', '--verbose', action='store_true', help="Changes the output to being very verbose")
4611 sel_print.add_argument('-f', '--fileloc', help='Parse a file instead of the BMC output')
4612 sel_print.set_defaults(func=selPrint)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004613
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004614 #sel list
4615 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")
4616 sel_list.add_argument("selNum", nargs='?', type=int, help="The SEL entry to get details on")
4617 sel_list.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004618
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004619 sel_get = sel_subparser.add_parser("get", help="Gets the verbose details of a specified SEL entry")
4620 sel_get.add_argument('selNum', type=int, help="the number of the SEL entry to get")
4621 sel_get.set_defaults(func=selList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004622
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004623 sel_clear = sel_subparser.add_parser("clear", help="Clears all entries from the SEL")
4624 sel_clear.set_defaults(func=selClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004625
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004626 sel_setResolved = sel_subparser.add_parser("resolve", help="Sets the sel entry to resolved")
Justin Thalere412dc22018-01-12 16:28:24 -06004627 sel_setResolved.add_argument('-n', '--selNum', type=int, help="the number of the SEL entry to resolve")
4628 sel_ResolveAll_sub = sel_setResolved.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
4629 sel_ResolveAll = sel_ResolveAll_sub.add_parser('all', help='Resolve all SEL entries')
4630 sel_ResolveAll.set_defaults(func=selResolveAll)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004631 sel_setResolved.set_defaults(func=selSetResolved)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004632
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004633 parser_chassis = subparsers.add_parser("chassis", help="Work with chassis power and status")
Justin Thalere412dc22018-01-12 16:28:24 -06004634 chas_sub = parser_chassis.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004635
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004636 parser_chassis.add_argument('status', action='store_true', help='Returns the current status of the platform')
4637 parser_chassis.set_defaults(func=chassis)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004638
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004639 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 -06004640 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 -06004641 parser_chasPower.set_defaults(func=chassisPower)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004642
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004643 #control the chassis identify led
4644 parser_chasIdent = chas_sub.add_parser("identify", help="Control the chassis identify led")
4645 parser_chasIdent.add_argument('identcmd', choices=['on', 'off', 'status'], help='The control option for the led: on, off, blink, status')
4646 parser_chasIdent.set_defaults(func=chassisIdent)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004647
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004648 #collect service data
4649 parser_servData = subparsers.add_parser("collect_service_data", help="Collect all bmc data needed for service")
4650 parser_servData.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
4651 parser_servData.set_defaults(func=collectServiceData)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004652
Justin Thalere412dc22018-01-12 16:28:24 -06004653 #system quick health check
4654 parser_healthChk = subparsers.add_parser("health_check", help="Work with platform sensors")
4655 parser_healthChk.set_defaults(func=healthCheck)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004656
Ravi Tejad8be0b42020-03-18 14:31:46 -05004657 #work with dumps
4658 parser_bmcdump = subparsers.add_parser("dump", help="Work with dumps")
4659 parser_bmcdump.add_argument("-t", "--dumpType", default='bmc', choices=['bmc','SystemDump'],help="Type of dump")
Justin Thalere412dc22018-01-12 16:28:24 -06004660 bmcDump_sub = parser_bmcdump.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thaler53bf2f12018-07-16 14:05:32 -05004661 bmcDump_sub.required = True
Ravi Tejad8be0b42020-03-18 14:31:46 -05004662 dump_Create = bmcDump_sub.add_parser('create', help="Create a dump of given type")
4663 dump_Create.set_defaults(func=dumpCreate)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004664
Ravi Tejad8be0b42020-03-18 14:31:46 -05004665 dump_list = bmcDump_sub.add_parser('list', help="list all dumps")
4666 dump_list.set_defaults(func=dumpList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004667
Ravi Tejad8be0b42020-03-18 14:31:46 -05004668 parserdumpdelete = bmcDump_sub.add_parser('delete', help="Delete dump")
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004669 parserdumpdelete.add_argument("-n", "--dumpNum", nargs='*', type=int, help="The Dump entry to delete")
Ravi Tejad8be0b42020-03-18 14:31:46 -05004670 parserdumpdelete.set_defaults(func=dumpDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004671
Justin Thalere412dc22018-01-12 16:28:24 -06004672 bmcDumpDelsub = parserdumpdelete.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Ravi Tejad8be0b42020-03-18 14:31:46 -05004673 deleteAllDumps = bmcDumpDelsub.add_parser('all', help='Delete all dumps')
4674 deleteAllDumps.set_defaults(func=dumpDeleteAll)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004675
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004676 parser_dumpretrieve = bmcDump_sub.add_parser('retrieve', help='Retrieve a dump file')
Ravi Tejad8be0b42020-03-18 14:31:46 -05004677 parser_dumpretrieve.add_argument("-n,", "--dumpNum", help="The Dump entry to retrieve")
4678 parser_dumpretrieve.add_argument("-s", "--dumpSaveLoc", help="The location to save the bmc dump file or file path for system dump")
4679 parser_dumpretrieve.set_defaults(func=dumpRetrieve)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004680
Justin Thaler22b1bb52018-03-15 13:31:32 -05004681 #bmc command for reseting the bmc
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004682 parser_bmc = subparsers.add_parser('bmc', help="Work with the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004683 bmc_sub = parser_bmc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004684 parser_BMCReset = bmc_sub.add_parser('reset', help='Reset the bmc' )
4685 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 -06004686 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.")
4687 parser_bmc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004688
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004689 #add alias to the bmc command
4690 parser_mc = subparsers.add_parser('mc', help="Work with the management controller")
Justin Thalere412dc22018-01-12 16:28:24 -06004691 mc_sub = parser_mc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004692 parser_MCReset = mc_sub.add_parser('reset', help='Reset the bmc' )
4693 parser_MCReset.add_argument('type', choices=['warm','cold'], help="Reboot the BMC")
4694 #parser_MCReset.add_argument('cold', action='store_true', help="Reboot the BMC and CLEAR the configuration")
4695 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 -06004696 parser_MCReset.set_defaults(func=bmcReset)
Justin Thalerf9aee3e2017-12-05 12:11:09 -06004697 parser_mc.set_defaults(func=bmc)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004698
Justin Thalere412dc22018-01-12 16:28:24 -06004699 #gard clear
4700 parser_gc = subparsers.add_parser("gardclear", help="Used to clear gard records")
4701 parser_gc.set_defaults(func=gardClear)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004702
Justin Thalere412dc22018-01-12 16:28:24 -06004703 #firmware_flash
4704 parser_fw = subparsers.add_parser("firmware", help="Work with the system firmware")
4705 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 -05004706 fwflash_subproc.required = True
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004707
Justin Thalere412dc22018-01-12 16:28:24 -06004708 fwflash = fwflash_subproc.add_parser('flash', help="Flash the system firmware")
4709 fwflash.add_argument('type', choices=['bmc', 'pnor'], help="image type to flash")
4710 fwflash.add_argument('-f', '--fileloc', required=True, help="The absolute path to the firmware image")
4711 fwflash.set_defaults(func=fwFlash)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004712
Justin Thaler22b1bb52018-03-15 13:31:32 -05004713 fwActivate = fwflash_subproc.add_parser('activate', help="Activate existing image on the bmc")
Justin Thalere412dc22018-01-12 16:28:24 -06004714 fwActivate.add_argument('imageID', help="The image ID to activate from the firmware list. Ex: 63c95399")
4715 fwActivate.set_defaults(func=activateFWImage)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004716
Justin Thaler22b1bb52018-03-15 13:31:32 -05004717 fwActivateStatus = fwflash_subproc.add_parser('activation_status', help="Check Status of activations")
4718 fwActivateStatus.set_defaults(func=activateStatus)
4719
Justin Thaler3d71d402018-07-24 14:35:39 -05004720 fwList = fwflash_subproc.add_parser('list', help="List all of the installed firmware")
4721 fwList.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4722 fwList.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004723
Justin Thaler3d71d402018-07-24 14:35:39 -05004724 fwprint = fwflash_subproc.add_parser('print', help="List all of the installed firmware")
4725 fwprint.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4726 fwprint.set_defaults(func=firmwareList)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004727
Adriana Kobylak5af2fad2018-11-08 12:33:43 -06004728 fwDelete = fwflash_subproc.add_parser('delete', help="Delete an existing firmware version")
4729 fwDelete.add_argument('versionID', help="The version ID to delete from the firmware list. Ex: 63c95399")
4730 fwDelete.set_defaults(func=deleteFWVersion)
4731
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004732 #logging
4733 parser_logging = subparsers.add_parser("logging", help="logging controls")
4734 logging_sub = parser_logging.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004735
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05004736 #turn rest api logging on/off
4737 parser_rest_logging = logging_sub.add_parser("rest_api", help="turn rest api logging on/off")
4738 parser_rest_logging.add_argument('rest_logging', choices=['on', 'off'], help='The control option for rest logging: on, off')
4739 parser_rest_logging.set_defaults(func=restLogging)
Deepak Kodihalli02d53282018-09-18 06:53:31 -05004740
4741 #remote logging
4742 parser_remote_logging = logging_sub.add_parser("remote_logging", help="Remote logging (rsyslog) commands")
4743 parser_remote_logging.add_argument('remote_logging', choices=['view', 'disable'], help='Remote logging (rsyslog) commands')
4744 parser_remote_logging.set_defaults(func=remoteLogging)
4745
4746 #configure remote logging
4747 parser_remote_logging_config = logging_sub.add_parser("remote_logging_config", help="Configure remote logging (rsyslog)")
4748 parser_remote_logging_config.add_argument("-a", "--address", required=True, help="Set IP address of rsyslog server")
4749 parser_remote_logging_config.add_argument("-p", "--port", required=True, type=int, help="Set Port of rsyslog server")
4750 parser_remote_logging_config.set_defaults(func=remoteLoggingConfig)
Dhruvaraj Subhashchandran64e7f6f2018-10-02 03:42:14 -05004751
4752 #certificate management
4753 parser_cert = subparsers.add_parser("certificate", help="Certificate management")
4754 certMgmt_subproc = parser_cert.add_subparsers(title='subcommands', description='valid certificate commands', help='sub-command help', dest='command')
4755
4756 certUpdate = certMgmt_subproc.add_parser('update', help="Update the certificate")
4757 certUpdate.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to update")
4758 certUpdate.add_argument('service', choices=['https', 'ldap'], help="Service to update")
4759 certUpdate.add_argument('-f', '--fileloc', required=True, help="The absolute path to the certificate file")
4760 certUpdate.set_defaults(func=certificateUpdate)
4761
4762 certDelete = certMgmt_subproc.add_parser('delete', help="Delete the certificate")
4763 certDelete.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to delete")
4764 certDelete.add_argument('service', choices=['https', 'ldap'], help="Service to delete the certificate")
4765 certDelete.set_defaults(func=certificateDelete)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06004766
Marri Devender Raodfe81ad2019-07-01 05:38:09 -05004767 certReplace = certMgmt_subproc.add_parser('replace',
4768 help="Replace the certificate")
4769 certReplace.add_argument('type', choices=['server', 'client', 'authority'],
4770 help="certificate type to replace")
4771 certReplace.add_argument('service', choices=['https', 'ldap'],
4772 help="Service to replace the certificate")
4773 certReplace.add_argument('-f', '--fileloc', required=True,
4774 help="The absolute path to the certificate file")
4775 certReplace.set_defaults(func=certificateReplace)
4776
Marri Devender Rao34646402019-07-01 05:46:03 -05004777 certDisplay = certMgmt_subproc.add_parser('display',
4778 help="Print the certificate")
4779 certDisplay.add_argument('type', choices=['server', 'client', 'authority'],
4780 help="certificate type to display")
4781 certDisplay.set_defaults(func=certificateDisplay)
4782
Marri Devender Raoa208ff82019-07-01 05:51:27 -05004783 certList = certMgmt_subproc.add_parser('list',
4784 help="Certificate list")
4785 certList.set_defaults(func=certificateList)
4786
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004787 certGenerateCSR = certMgmt_subproc.add_parser('generatecsr', help="Generate CSR")
4788 certGenerateCSR.add_argument('type', choices=['server', 'client', 'authority'],
4789 help="Generate CSR")
4790 certGenerateCSR.add_argument('city',
4791 help="The city or locality of the organization making the request")
4792 certGenerateCSR.add_argument('commonName',
4793 help="The fully qualified domain name of the component that is being secured.")
4794 certGenerateCSR.add_argument('country',
4795 help="The country of the organization making the request")
4796 certGenerateCSR.add_argument('organization',
4797 help="The name of the organization making the request.")
4798 certGenerateCSR.add_argument('organizationUnit',
4799 help="The name of the unit or division of the organization making the request.")
4800 certGenerateCSR.add_argument('state',
4801 help="The state, province, or region of the organization making the request.")
4802 certGenerateCSR.add_argument('keyPairAlgorithm', choices=['RSA', 'EC'],
4803 help="The type of key pair for use with signing algorithms.")
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004804 certGenerateCSR.add_argument('keyCurveId',
4805 help="The curve ID to be used with the key, if needed based on the value of the 'KeyPairAlgorithm' parameter.")
4806 certGenerateCSR.add_argument('contactPerson',
4807 help="The name of the user making the request")
4808 certGenerateCSR.add_argument('email',
4809 help="The email address of the contact within the organization")
4810 certGenerateCSR.add_argument('alternativeNames',
4811 help="Additional hostnames of the component that is being secured")
4812 certGenerateCSR.add_argument('givenname',
4813 help="The given name of the user making the request")
4814 certGenerateCSR.add_argument('surname',
4815 help="The surname of the user making the request")
4816 certGenerateCSR.add_argument('unstructuredname',
4817 help="he unstructured name of the subject")
4818 certGenerateCSR.add_argument('initials',
4819 help="The initials of the user making the request")
Marri Devender Rao3cdf8ae2019-07-01 06:01:40 -05004820 certGenerateCSR.set_defaults(func=certificateGenerateCSR)
4821
Matt Spinler7d426c22018-09-24 14:42:07 -05004822 # local users
4823 parser_users = subparsers.add_parser("local_users", help="Work with local users")
4824 parser_users.add_argument('local_users', choices=['disableall','enableall', 'queryenabled'], help="Disable, enable or query local user accounts")
4825 parser_users.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
4826 parser_users.set_defaults(func=localUsers)
4827
Ratan Gupta9166cd22018-10-01 18:09:40 +05304828 #LDAP
4829 parser_ldap = subparsers.add_parser("ldap", help="LDAP controls")
4830 ldap_sub = parser_ldap.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
4831
4832 #configure and enable LDAP
4833 parser_ldap_config = ldap_sub.add_parser("enable", help="Configure and enables the LDAP")
4834 parser_ldap_config.add_argument("-a", "--uri", required=True, help="Set LDAP server URI")
4835 parser_ldap_config.add_argument("-B", "--bindDN", required=True, help="Set the bind DN of the LDAP server")
4836 parser_ldap_config.add_argument("-b", "--baseDN", required=True, help="Set the base DN of the LDAP server")
4837 parser_ldap_config.add_argument("-p", "--bindPassword", required=True, help="Set the bind password of the LDAP server")
4838 parser_ldap_config.add_argument("-S", "--scope", choices=['sub','one', 'base'],
4839 help='Specifies the search scope:subtree, one level or base object.')
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004840 parser_ldap_config.add_argument("-t", "--serverType", required=True, choices=['ActiveDirectory','OpenLDAP'],
Ratan Gupta9166cd22018-10-01 18:09:40 +05304841 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004842 parser_ldap_config.add_argument("-g","--groupAttrName", required=False, default='', help="Group Attribute Name")
4843 parser_ldap_config.add_argument("-u","--userAttrName", required=False, default='', help="User Attribute Name")
4844 parser_ldap_config.set_defaults(func=enableLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05304845
4846 # disable LDAP
4847 parser_disable_ldap = ldap_sub.add_parser("disable", help="disables the LDAP")
4848 parser_disable_ldap.set_defaults(func=disableLDAP)
Nagaraju Goruganti7d1fe172018-11-13 06:09:29 -06004849 # view-config
4850 parser_ldap_config = \
4851 ldap_sub.add_parser("view-config", help="prints out a list of all \
4852 LDAPS's configured properties")
4853 parser_ldap_config.set_defaults(func=viewLDAPConfig)
Ratan Gupta9166cd22018-10-01 18:09:40 +05304854
Ratan Guptafeee6372018-10-17 23:25:51 +05304855 #create group privilege mapping
4856 parser_ldap_mapper = ldap_sub.add_parser("privilege-mapper", help="LDAP group privilege controls")
4857 parser_ldap_mapper_sub = parser_ldap_mapper.add_subparsers(title='subcommands', description='valid subcommands',
4858 help="sub-command help", dest='command')
4859
4860 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 -05004861 parser_ldap_mapper_create.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4862 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304863 parser_ldap_mapper_create.add_argument("-g","--groupName",required=True,help="Group Name")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004864 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 +05304865 parser_ldap_mapper_create.set_defaults(func=createPrivilegeMapping)
4866
4867 #list group privilege mapping
4868 parser_ldap_mapper_list = parser_ldap_mapper_sub.add_parser("list",help="List privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004869 parser_ldap_mapper_list.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4870 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304871 parser_ldap_mapper_list.set_defaults(func=listPrivilegeMapping)
4872
4873 #delete group privilege mapping
4874 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("delete",help="Delete privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004875 parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4876 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Ratan Guptafeee6372018-10-17 23:25:51 +05304877 parser_ldap_mapper_delete.add_argument("-g","--groupName",required=True,help="Group Name")
4878 parser_ldap_mapper_delete.set_defaults(func=deletePrivilegeMapping)
4879
Sivas SRR78835272018-11-27 05:27:19 -06004880 #deleteAll group privilege mapping
4881 parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("purge",help="Delete All privilege mapping")
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05004882 parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
4883 help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
Sivas SRR78835272018-11-27 05:27:19 -06004884 parser_ldap_mapper_delete.set_defaults(func=deleteAllPrivilegeMapping)
4885
Marri Devender Rao2c2a5162018-11-05 08:57:11 -06004886 # set local user password
4887 parser_set_password = subparsers.add_parser("set_password",
4888 help="Set password of local user")
4889 parser_set_password.add_argument( "-p", "--password", required=True,
4890 help="Password of local user")
4891 parser_set_password.set_defaults(func=setPassword)
4892
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004893 # network
4894 parser_nw = subparsers.add_parser("network", help="network controls")
4895 nw_sub = parser_nw.add_subparsers(title='subcommands',
4896 description='valid subcommands',
4897 help="sub-command help",
4898 dest='command')
4899
4900 # enable DHCP
4901 parser_enable_dhcp = nw_sub.add_parser("enableDHCP",
4902 help="enables the DHCP on given "
4903 "Interface")
4904 parser_enable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004905 help="Name of the ethernet interface(it can"
4906 "be obtained by the "
4907 "command:network view-config)"
4908 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004909 parser_enable_dhcp.set_defaults(func=enableDHCP)
4910
4911 # disable DHCP
4912 parser_disable_dhcp = nw_sub.add_parser("disableDHCP",
4913 help="disables the DHCP on given "
4914 "Interface")
4915 parser_disable_dhcp.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004916 help="Name of the ethernet interface(it can"
4917 "be obtained by the "
4918 "command:network view-config)"
4919 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004920 parser_disable_dhcp.set_defaults(func=disableDHCP)
4921
4922 # get HostName
4923 parser_gethostname = nw_sub.add_parser("getHostName",
4924 help="prints out HostName")
4925 parser_gethostname.set_defaults(func=getHostname)
4926
4927 # set HostName
4928 parser_sethostname = nw_sub.add_parser("setHostName", help="sets HostName")
4929 parser_sethostname.add_argument("-H", "--HostName", required=True,
4930 help="A HostName for the BMC")
4931 parser_sethostname.set_defaults(func=setHostname)
4932
4933 # get domainname
4934 parser_getdomainname = nw_sub.add_parser("getDomainName",
4935 help="prints out DomainName of "
4936 "given Interface")
4937 parser_getdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004938 help="Name of the ethernet interface(it "
4939 "can be obtained by the "
4940 "command:network view-config)"
4941 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004942 parser_getdomainname.set_defaults(func=getDomainName)
4943
4944 # set domainname
4945 parser_setdomainname = nw_sub.add_parser("setDomainName",
4946 help="sets DomainName of given "
4947 "Interface")
4948 parser_setdomainname.add_argument("-D", "--DomainName", required=True,
4949 help="Ex: DomainName=Domain1,Domain2,...")
4950 parser_setdomainname.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004951 help="Name of the ethernet interface(it "
4952 "can be obtained by the "
4953 "command:network view-config)"
4954 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004955 parser_setdomainname.set_defaults(func=setDomainName)
4956
4957 # get MACAddress
4958 parser_getmacaddress = nw_sub.add_parser("getMACAddress",
4959 help="prints out MACAddress the "
4960 "given Interface")
4961 parser_getmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004962 help="Name of the ethernet interface(it "
4963 "can be obtained by the "
4964 "command:network view-config)"
4965 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004966 parser_getmacaddress.set_defaults(func=getMACAddress)
4967
4968 # set MACAddress
4969 parser_setmacaddress = nw_sub.add_parser("setMACAddress",
4970 help="sets MACAddress")
4971 parser_setmacaddress.add_argument("-MA", "--MACAddress", required=True,
4972 help="A MACAddress for the given "
4973 "Interface")
4974 parser_setmacaddress.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06004975 help="Name of the ethernet interface(it can"
4976 "be obtained by the "
4977 "command:network view-config)"
4978 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06004979 parser_setmacaddress.set_defaults(func=setMACAddress)
4980
4981 # get DefaultGW
4982 parser_getdefaultgw = nw_sub.add_parser("getDefaultGW",
4983 help="prints out DefaultGateway "
4984 "the BMC")
4985 parser_getdefaultgw.set_defaults(func=getDefaultGateway)
4986
4987 # set DefaultGW
4988 parser_setdefaultgw = nw_sub.add_parser("setDefaultGW",
4989 help="sets DefaultGW")
4990 parser_setdefaultgw.add_argument("-GW", "--DefaultGW", required=True,
4991 help="A DefaultGateway for the BMC")
4992 parser_setdefaultgw.set_defaults(func=setDefaultGateway)
4993
4994 # view network Config
4995 parser_ldap_config = nw_sub.add_parser("view-config", help="prints out a "
4996 "list of all network's configured "
4997 "properties")
4998 parser_ldap_config.set_defaults(func=viewNWConfig)
4999
5000 # get DNS
5001 parser_getDNS = nw_sub.add_parser("getDNS",
5002 help="prints out DNS servers on the "
5003 "given interface")
5004 parser_getDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005005 help="Name of the ethernet interface(it can"
5006 "be obtained by the "
5007 "command:network view-config)"
5008 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005009 parser_getDNS.set_defaults(func=getDNS)
5010
5011 # set DNS
5012 parser_setDNS = nw_sub.add_parser("setDNS",
5013 help="sets DNS servers on the given "
5014 "interface")
5015 parser_setDNS.add_argument("-d", "--DNSServers", required=True,
5016 help="Ex: DNSSERVERS=DNS1,DNS2,...")
5017 parser_setDNS.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005018 help="Name of the ethernet interface(it can"
5019 "be obtained by the "
5020 "command:network view-config)"
5021 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005022 parser_setDNS.set_defaults(func=setDNS)
5023
5024 # get NTP
5025 parser_getNTP = nw_sub.add_parser("getNTP",
5026 help="prints out NTP servers on the "
5027 "given interface")
5028 parser_getNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005029 help="Name of the ethernet interface(it can"
5030 "be obtained by the "
5031 "command:network view-config)"
5032 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005033 parser_getNTP.set_defaults(func=getNTP)
5034
5035 # set NTP
5036 parser_setNTP = nw_sub.add_parser("setNTP",
5037 help="sets NTP servers on the given "
5038 "interface")
5039 parser_setNTP.add_argument("-N", "--NTPServers", required=True,
5040 help="Ex: NTPSERVERS=NTP1,NTP2,...")
5041 parser_setNTP.add_argument("-I", "--Interface", required=True,
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005042 help="Name of the ethernet interface(it can"
5043 "be obtained by the "
5044 "command:network view-config)"
5045 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
Nagaraju Goruganti9908bcf2018-11-14 22:07:25 -06005046 parser_setNTP.set_defaults(func=setNTP)
5047
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005048 # configure IP
5049 parser_ip_config = nw_sub.add_parser("addIP", help="Sets IP address to"
5050 "given interface")
5051 parser_ip_config.add_argument("-a", "--address", required=True,
5052 help="IP address of given interface")
5053 parser_ip_config.add_argument("-gw", "--gateway", required=False, default='',
5054 help="The gateway for given interface")
5055 parser_ip_config.add_argument("-l", "--prefixLength", required=True,
5056 help="The prefixLength of IP address")
Sunitha Harish0baf6372019-07-31 03:59:03 -05005057 parser_ip_config.add_argument("-p", "--type", required=True,
5058 choices=['ipv4', 'ipv6'],
Nagaraju Goruganti97a20602018-11-16 03:06:08 -06005059 help="The protocol type of the given"
5060 "IP address")
5061 parser_ip_config.add_argument("-I", "--Interface", required=True,
5062 help="Name of the ethernet interface(it can"
5063 "be obtained by the "
5064 "command:network view-config)"
5065 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5066 parser_ip_config.set_defaults(func=addIP)
5067
5068 # getIP
5069 parser_getIP = nw_sub.add_parser("getIP", help="prints out IP address"
5070 "of given interface")
5071 parser_getIP.add_argument("-I", "--Interface", required=True,
5072 help="Name of the ethernet interface(it can"
5073 "be obtained by the command:network view-config)"
5074 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5075 parser_getIP.set_defaults(func=getIP)
5076
5077 # rmIP
5078 parser_rmIP = nw_sub.add_parser("rmIP", help="deletes IP address"
5079 "of given interface")
5080 parser_rmIP.add_argument("-a", "--address", required=True,
5081 help="IP address to remove form given Interface")
5082 parser_rmIP.add_argument("-I", "--Interface", required=True,
5083 help="Name of the ethernet interface(it can"
5084 "be obtained by the command:network view-config)"
5085 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5086 parser_rmIP.set_defaults(func=deleteIP)
5087
Nagaraju Gorugantif21d43c2018-11-19 10:47:19 -06005088 # add VLAN
5089 parser_create_vlan = nw_sub.add_parser("addVLAN", help="enables VLAN "
5090 "on given interface with given "
5091 "VLAN Identifier")
5092 parser_create_vlan.add_argument("-I", "--Interface", required=True,
5093 choices=['eth0', 'eth1'],
5094 help="Name of the ethernet interface")
5095 parser_create_vlan.add_argument("-n", "--Identifier", required=True,
5096 help="VLAN Identifier")
5097 parser_create_vlan.set_defaults(func=addVLAN)
5098
5099 # delete VLAN
5100 parser_delete_vlan = nw_sub.add_parser("deleteVLAN", help="disables VLAN "
5101 "on given interface with given "
5102 "VLAN Identifier")
5103 parser_delete_vlan.add_argument("-I", "--Interface", required=True,
5104 help="Name of the ethernet interface(it can"
5105 "be obtained by the "
5106 "command:network view-config)"
5107 "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
5108 parser_delete_vlan.set_defaults(func=deleteVLAN)
5109
5110 # viewDHCPConfig
5111 parser_viewDHCPConfig = nw_sub.add_parser("viewDHCPConfig",
5112 help="Shows DHCP configured "
5113 "Properties")
5114 parser_viewDHCPConfig.set_defaults(func=viewDHCPConfig)
5115
5116 # configureDHCP
5117 parser_configDHCP = nw_sub.add_parser("configureDHCP",
5118 help="Configures/updates DHCP "
5119 "Properties")
5120 parser_configDHCP.add_argument("-d", "--DNSEnabled", type=str2bool,
5121 required=True, help="Sets DNSEnabled property")
5122 parser_configDHCP.add_argument("-n", "--HostNameEnabled", type=str2bool,
5123 required=True,
5124 help="Sets HostNameEnabled property")
5125 parser_configDHCP.add_argument("-t", "--NTPEnabled", type=str2bool,
5126 required=True,
5127 help="Sets NTPEnabled property")
5128 parser_configDHCP.add_argument("-s", "--SendHostNameEnabled", type=str2bool,
5129 required=True,
5130 help="Sets SendHostNameEnabled property")
5131 parser_configDHCP.set_defaults(func=configureDHCP)
5132
5133 # network factory reset
5134 parser_nw_reset = nw_sub.add_parser("nwReset",
5135 help="Resets networks setting to "
5136 "factory defaults. "
5137 "note:Reset settings will be applied "
5138 "after BMC reboot")
5139 parser_nw_reset.set_defaults(func=nwReset)
5140
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005141 return parser
5142
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005143def main(argv=None):
Justin Thalere412dc22018-01-12 16:28:24 -06005144 """
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005145 main function for running the command line utility as a sub application
5146 """
5147 global toolVersion
Joy Onyerikwu182c3a32019-10-15 08:33:59 -05005148 toolVersion = "1.18"
Sunitha Harishc99faba2019-07-19 06:55:22 -05005149 global isRedfishSupport
RAJESWARAN THILLAIGOVINDAN87f087b2019-05-08 04:15:26 -05005150
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005151 parser = createCommandParser()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005152 args = parser.parse_args(argv)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005153
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005154 totTimeStart = int(round(time.time()*1000))
5155
5156 if(sys.version_info < (3,0)):
5157 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
5158 if sys.version_info >= (3,0):
5159 requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
Justin Thalere412dc22018-01-12 16:28:24 -06005160 if (args.version):
Justin Thaler22b1bb52018-03-15 13:31:32 -05005161 print("Version: "+ toolVersion)
Justin Thalere412dc22018-01-12 16:28:24 -06005162 sys.exit(0)
5163 if (hasattr(args, 'fileloc') and args.fileloc is not None and 'print' in args.command):
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005164 mysess = None
Justin Thalere412dc22018-01-12 16:28:24 -06005165 print(selPrint('N/A', args, mysess))
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005166 else:
Justin Thalere412dc22018-01-12 16:28:24 -06005167 if(hasattr(args, 'host') and hasattr(args,'user')):
5168 if (args.askpw):
5169 pw = getpass.getpass()
5170 elif(args.PW is not None):
5171 pw = args.PW
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05005172 elif(args.PWenvvar):
5173 pw = os.environ['OPENBMCTOOL_PASSWORD']
Justin Thalere412dc22018-01-12 16:28:24 -06005174 else:
5175 print("You must specify a password")
5176 sys.exit()
5177 logintimeStart = int(round(time.time()*1000))
Joy Onyerikwu182c3a32019-10-15 08:33:59 -05005178 mysess = login(args.host, args.user, pw, args.json,
5179 args.command == 'set_password')
Sunitha Harish336cda22019-07-23 02:02:52 -05005180 if(mysess == None):
5181 print("Login Failed!")
5182 sys.exit()
Justin Thalera9415b42018-05-25 19:40:13 -05005183 if(sys.version_info < (3,0)):
5184 if isinstance(mysess, basestring):
5185 print(mysess)
5186 sys.exit(1)
5187 elif sys.version_info >= (3,0):
5188 if isinstance(mysess, str):
5189 print(mysess)
5190 sys.exit(1)
Justin Thalere412dc22018-01-12 16:28:24 -06005191 logintimeStop = int(round(time.time()*1000))
Sunitha Harishc99faba2019-07-19 06:55:22 -05005192 isRedfishSupport = redfishSupportPresent(args.host,mysess)
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005193 commandTimeStart = int(round(time.time()*1000))
Justin Thalere412dc22018-01-12 16:28:24 -06005194 output = args.func(args.host, args, mysess)
5195 commandTimeStop = int(round(time.time()*1000))
Justin Thaler761484a2019-03-26 19:20:23 -05005196 if isinstance(output, dict):
5197 print(json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
5198 else:
5199 print(output)
Justin Thalere412dc22018-01-12 16:28:24 -06005200 if (mysess is not None):
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005201 logout(args.host, args.user, pw, mysess, args.json)
5202 if(args.procTime):
Justin Thalere412dc22018-01-12 16:28:24 -06005203 print("Total time: " + str(int(round(time.time()*1000))- totTimeStart))
5204 print("loginTime: " + str(logintimeStop - logintimeStart))
5205 print("command Time: " + str(commandTimeStop - commandTimeStart))
5206 else:
Joseph Reynoldsa2d54c52019-06-11 22:02:57 -05005207 print("usage:\n"
5208 " OPENBMCTOOL_PASSWORD=secret # if using -E\n"
5209 " openbmctool.py [-h] -H HOST -U USER {-A | -P PW | -E} [-j]\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06005210 "\t[-t POLICYTABLELOC] [-V]\n" +
Deepak Kodihalli22d4df02018-09-18 06:52:43 -05005211 "\t{fru,sensors,sel,chassis,collect_service_data, \
5212 health_check,dump,bmc,mc,gardclear,firmware,logging}\n" +
Justin Thalere412dc22018-01-12 16:28:24 -06005213 "\t...\n" +
5214 "openbmctool.py: error: the following arguments are required: -H/--host, -U/--user")
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005215 sys.exit()
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005216
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005217if __name__ == '__main__':
Justin Thalere412dc22018-01-12 16:28:24 -06005218 """
5219 main function when called from the command line
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005220
5221 """
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005222 import sys
Nagaraju Gorugantic1a00af2018-11-07 00:52:11 -06005223
Justin Thalerf9aee3e2017-12-05 12:11:09 -06005224 isTTY = sys.stdout.isatty()
5225 assert sys.version_info >= (2,7)
5226 main()