| Justin Thaler | b8807ce | 2018-05-25 19:16:20 -0500 | [diff] [blame] | 1 | #!/usr/bin/python3 | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2 | """ | 
| Joseph Reynolds | a2d54c5 | 2019-06-11 22:02:57 -0500 | [diff] [blame] | 3 | Copyright 2017,2019 IBM Corporation | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 4 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 5 | 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 Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 17 | import argparse | 
|  | 18 | import requests | 
|  | 19 | import getpass | 
|  | 20 | import json | 
|  | 21 | import os | 
|  | 22 | import urllib3 | 
|  | 23 | import time, datetime | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 24 | import binascii | 
|  | 25 | import subprocess | 
|  | 26 | import platform | 
|  | 27 | import zipfile | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 28 | import tarfile | 
|  | 29 | import tempfile | 
|  | 30 | import hashlib | 
| Justin Thaler | a6b5df7 | 2018-07-16 11:10:07 -0500 | [diff] [blame] | 31 | import re | 
| Justin Thaler | 24d4efa | 2018-11-08 22:48:10 -0600 | [diff] [blame] | 32 | import uuid | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 33 |  | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 34 | jsonHeader = {'Content-Type' : 'application/json'} | 
|  | 35 | xAuthHeader = {} | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 36 | baseTimeout = 60 | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 37 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 38 | def hilight(textToColor, color, bold): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 39 | """ | 
|  | 40 | Used to add highlights to various text for displaying in a terminal | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 41 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 42 | @param textToColor: string, the text to be colored | 
|  | 43 | @param color: string, used to color the text red or green | 
|  | 44 | @param bold: boolean, used to bold the textToColor | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 45 | @return: Buffered reader containing the modified string. | 
|  | 46 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 47 | if(sys.platform.__contains__("win")): | 
|  | 48 | if(color == "red"): | 
|  | 49 | os.system('color 04') | 
|  | 50 | elif(color == "green"): | 
|  | 51 | os.system('color 02') | 
|  | 52 | else: | 
|  | 53 | os.system('color') #reset to default | 
|  | 54 | return textToColor | 
|  | 55 | else: | 
|  | 56 | attr = [] | 
|  | 57 | if(color == "red"): | 
|  | 58 | attr.append('31') | 
|  | 59 | elif(color == "green"): | 
|  | 60 | attr.append('32') | 
|  | 61 | else: | 
|  | 62 | attr.append('0') | 
|  | 63 | if bold: | 
|  | 64 | attr.append('1') | 
|  | 65 | else: | 
|  | 66 | attr.append('0') | 
|  | 67 | return '\x1b[%sm%s\x1b[0m' % (';'.join(attr),textToColor) | 
|  | 68 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 69 | def connectionErrHandler(jsonFormat, errorStr, err): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 70 | """ | 
|  | 71 | Error handler various connection errors to bmcs | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 72 |  | 
|  | 73 | @param jsonFormat: boolean, used to output in json format with an error code. | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 74 | @param errorStr: string, used to color the text red or green | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 75 | @param err: string, the text from the exception | 
|  | 76 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 77 | if errorStr == "Timeout": | 
|  | 78 | if not jsonFormat: | 
|  | 79 | return("FQPSPIN0000M: Connection timed out. Ensure you have network connectivity to the bmc") | 
|  | 80 | else: | 
| Justin Thaler | 115bca7 | 2018-05-25 19:29:08 -0500 | [diff] [blame] | 81 | conerror = {} | 
|  | 82 | conerror['CommonEventID'] = 'FQPSPIN0000M' | 
|  | 83 | conerror['sensor']="N/A" | 
|  | 84 | conerror['state']="N/A" | 
|  | 85 | conerror['additionalDetails'] = "N/A" | 
|  | 86 | conerror['Message']="Connection timed out. Ensure you have network connectivity to the BMC" | 
|  | 87 | 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." | 
|  | 88 | conerror['Serviceable']="Yes" | 
|  | 89 | conerror['CallHomeCandidate']= "No" | 
|  | 90 | conerror['Severity'] = "Critical" | 
|  | 91 | conerror['EventType'] = "Communication Failure/Timeout" | 
|  | 92 | conerror['VMMigrationFlag'] = "Yes" | 
|  | 93 | conerror["AffectedSubsystem"] = "Interconnect (Networking)" | 
|  | 94 | conerror["timestamp"] = str(int(time.time())) | 
|  | 95 | conerror["UserAction"] = "Verify network connectivity between the two systems and the bmc is functional." | 
|  | 96 | eventdict = {} | 
|  | 97 | eventdict['event0'] = conerror | 
|  | 98 | eventdict['numAlerts'] = '1' | 
| Justin Thaler | 115bca7 | 2018-05-25 19:29:08 -0500 | [diff] [blame] | 99 | errorMessageStr = errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 100 | return(errorMessageStr) | 
|  | 101 | elif errorStr == "ConnectionError": | 
|  | 102 | if not jsonFormat: | 
|  | 103 | return("FQPSPIN0001M: " + str(err)) | 
|  | 104 | else: | 
| Justin Thaler | 115bca7 | 2018-05-25 19:29:08 -0500 | [diff] [blame] | 105 | conerror = {} | 
|  | 106 | conerror['CommonEventID'] = 'FQPSPIN0001M' | 
|  | 107 | conerror['sensor']="N/A" | 
|  | 108 | conerror['state']="N/A" | 
|  | 109 | conerror['additionalDetails'] = str(err) | 
|  | 110 | conerror['Message']="Connection Error. View additional details for more information" | 
|  | 111 | conerror['LengthyDescription'] = "A connection error to the specified BMC occurred and additional details are provided. Review these details to resolve the issue." | 
|  | 112 | conerror['Serviceable']="Yes" | 
|  | 113 | conerror['CallHomeCandidate']= "No" | 
|  | 114 | conerror['Severity'] = "Critical" | 
|  | 115 | conerror['EventType'] = "Communication Failure/Timeout" | 
|  | 116 | conerror['VMMigrationFlag'] = "Yes" | 
|  | 117 | conerror["AffectedSubsystem"] = "Interconnect (Networking)" | 
|  | 118 | conerror["timestamp"] = str(int(time.time())) | 
|  | 119 | conerror["UserAction"] = "Correct the issue highlighted in additional details and try again" | 
|  | 120 | eventdict = {} | 
|  | 121 | eventdict['event0'] = conerror | 
|  | 122 | eventdict['numAlerts'] = '1' | 
| Justin Thaler | 115bca7 | 2018-05-25 19:29:08 -0500 | [diff] [blame] | 123 | errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 124 | return(errorMessageStr) | 
| Justin Thaler | 115bca7 | 2018-05-25 19:29:08 -0500 | [diff] [blame] | 125 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 126 | else: | 
|  | 127 | return("Unknown Error: "+ str(err)) | 
|  | 128 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 129 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 130 | def setColWidth(keylist, numCols, dictForOutput, colNames): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 131 | """ | 
|  | 132 | Sets the output width of the columns to display | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 133 |  | 
|  | 134 | @param keylist: list, list of strings representing the keys for the dictForOutput | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 135 | @param numcols: the total number of columns in the final output | 
|  | 136 | @param dictForOutput: dictionary, contains the information to print to the screen | 
|  | 137 | @param colNames: list, The strings to use for the column headings, in order of the keylist | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 138 | @return: A list of the column widths for each respective column. | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 139 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 140 | colWidths = [] | 
|  | 141 | for x in range(0, numCols): | 
|  | 142 | colWidths.append(0) | 
|  | 143 | for key in dictForOutput: | 
|  | 144 | for x in range(0, numCols): | 
|  | 145 | colWidths[x] = max(colWidths[x], len(str(dictForOutput[key][keylist[x]]))) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 146 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 147 | for x in range(0, numCols): | 
|  | 148 | colWidths[x] = max(colWidths[x], len(colNames[x])) +2 | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 149 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 150 | return colWidths | 
|  | 151 |  | 
|  | 152 | def loadPolicyTable(pathToPolicyTable): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 153 | """ | 
|  | 154 | loads a json based policy table into a dictionary | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 155 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 156 | @param value: boolean, the value to convert | 
|  | 157 | @return: A string of "Yes" or "No" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 158 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 159 | policyTable = {} | 
|  | 160 | if(os.path.exists(pathToPolicyTable)): | 
|  | 161 | with open(pathToPolicyTable, 'r') as stream: | 
|  | 162 | try: | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 163 | contents =json.load(stream) | 
|  | 164 | policyTable = contents['events'] | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 165 | except Exception as err: | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 166 | print(err) | 
|  | 167 | return policyTable | 
|  | 168 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 169 |  | 
|  | 170 | def boolToString(value): | 
|  | 171 | """ | 
|  | 172 | converts a boolean value to a human readable string value | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 173 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 174 | @param value: boolean, the value to convert | 
|  | 175 | @return: A string of "Yes" or "No" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 176 | """ | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 177 | if(value): | 
|  | 178 | return "Yes" | 
|  | 179 | else: | 
|  | 180 | return "No" | 
|  | 181 |  | 
| Justin Thaler | a6b5df7 | 2018-07-16 11:10:07 -0500 | [diff] [blame] | 182 | def stringToInt(text): | 
|  | 183 | """ | 
|  | 184 | returns an integer if the string can be converted, otherwise returns the string | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 185 |  | 
| Justin Thaler | a6b5df7 | 2018-07-16 11:10:07 -0500 | [diff] [blame] | 186 | @param text: the string to try to convert to an integer | 
|  | 187 | """ | 
|  | 188 | if text.isdigit(): | 
|  | 189 | return int(text) | 
|  | 190 | else: | 
|  | 191 | return text | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 192 |  | 
| Justin Thaler | a6b5df7 | 2018-07-16 11:10:07 -0500 | [diff] [blame] | 193 | def naturalSort(text): | 
|  | 194 | """ | 
|  | 195 | provides a way to naturally sort a list | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 196 |  | 
| Justin Thaler | a6b5df7 | 2018-07-16 11:10:07 -0500 | [diff] [blame] | 197 | @param text: the key to convert for sorting | 
|  | 198 | @return list containing the broken up string parts by integers and strings | 
|  | 199 | """ | 
|  | 200 | stringPartList = [] | 
|  | 201 | for c in re.split('(\d+)', text): | 
|  | 202 | stringPartList.append(stringToInt(c)) | 
|  | 203 | return stringPartList | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 204 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 205 | def tableDisplay(keylist, colNames, output): | 
|  | 206 | """ | 
|  | 207 | Logs into the BMC and creates a session | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 208 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 209 | @param keylist: list, keys for the output dictionary, ordered by colNames | 
|  | 210 | @param colNames: Names for the Table of the columns | 
|  | 211 | @param output: The dictionary of data to display | 
|  | 212 | @return: Session object | 
|  | 213 | """ | 
|  | 214 | colWidth = setColWidth(keylist, len(colNames), output, colNames) | 
|  | 215 | row = "" | 
|  | 216 | outputText = "" | 
|  | 217 | for i in range(len(colNames)): | 
|  | 218 | if (i != 0): row = row + "| " | 
|  | 219 | row = row + colNames[i].ljust(colWidth[i]) | 
|  | 220 | outputText += row + "\n" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 221 |  | 
| Justin Thaler | a6b5df7 | 2018-07-16 11:10:07 -0500 | [diff] [blame] | 222 | output_keys = list(output.keys()) | 
|  | 223 | output_keys.sort(key=naturalSort) | 
|  | 224 | for key in output_keys: | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 225 | row = "" | 
| Justin Thaler | 8fe0c73 | 2018-07-24 14:32:35 -0500 | [diff] [blame] | 226 | for i in range(len(keylist)): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 227 | if (i != 0): row = row + "| " | 
|  | 228 | row = row + output[key][keylist[i]].ljust(colWidth[i]) | 
|  | 229 | outputText += row + "\n" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 230 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 231 | return outputText | 
|  | 232 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 233 | def checkFWactivation(host, args, session): | 
|  | 234 | """ | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 235 | Checks the software inventory for an image that is being activated. | 
|  | 236 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 237 | @return: True if an image is being activated, false is no activations are happening | 
|  | 238 | """ | 
|  | 239 | url="https://"+host+"/xyz/openbmc_project/software/enumerate" | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 240 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 241 | resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 242 | except(requests.exceptions.Timeout): | 
|  | 243 | print(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 244 | return(True) | 
|  | 245 | except(requests.exceptions.ConnectionError) as err: | 
|  | 246 | print( connectionErrHandler(args.json, "ConnectionError", err)) | 
|  | 247 | return True | 
| Justin Thaler | 3a5771b | 2019-01-23 14:31:52 -0600 | [diff] [blame] | 248 | fwInfo = resp.json()['data'] | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 249 | for key in fwInfo: | 
|  | 250 | if 'Activation' in fwInfo[key]: | 
|  | 251 | if 'Activating' in fwInfo[key]['Activation'] or 'Activating' in fwInfo[key]['RequestedActivation']: | 
|  | 252 | return True | 
|  | 253 | return False | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 254 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 255 | def login(host, username, pw,jsonFormat): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 256 | """ | 
|  | 257 | Logs into the BMC and creates a session | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 258 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 259 | @param host: string, the hostname or IP address of the bmc to log into | 
|  | 260 | @param username: The user name for the bmc to log into | 
|  | 261 | @param pw: The password for the BMC to log into | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 262 | @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true. | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 263 | @return: Session object | 
|  | 264 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 265 | if(jsonFormat==False): | 
|  | 266 | print("Attempting login...") | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 267 | mysess = requests.session() | 
|  | 268 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 269 | r = mysess.post('https://'+host+'/login', headers=jsonHeader, json = {"data": [username, pw]}, verify=False, timeout=baseTimeout) | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 270 |  | 
|  | 271 | cookie = r.headers['Set-Cookie'] | 
|  | 272 | match = re.search('SESSION=(\w+);', cookie) | 
|  | 273 | if match: | 
|  | 274 | xAuthHeader['X-Auth-Token'] = match.group(1) | 
|  | 275 | jsonHeader.update(xAuthHeader) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 276 | loginMessage = json.loads(r.text) | 
|  | 277 | if (loginMessage['status'] != "ok"): | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 278 | print(loginMessage["data"]["description"].encode('utf-8')) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 279 | sys.exit(1) | 
|  | 280 | #         if(sys.version_info < (3,0)): | 
|  | 281 | #             urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) | 
|  | 282 | #         if sys.version_info >= (3,0): | 
|  | 283 | #             requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning) | 
|  | 284 | return mysess | 
|  | 285 | except(requests.exceptions.Timeout): | 
| Justin Thaler | 115bca7 | 2018-05-25 19:29:08 -0500 | [diff] [blame] | 286 | return (connectionErrHandler(jsonFormat, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 287 | except(requests.exceptions.ConnectionError) as err: | 
| Justin Thaler | 115bca7 | 2018-05-25 19:29:08 -0500 | [diff] [blame] | 288 | return (connectionErrHandler(jsonFormat, "ConnectionError", err)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 289 |  | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 290 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 291 | def logout(host, username, pw, session, jsonFormat): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 292 | """ | 
|  | 293 | Logs out of the bmc and terminates the session | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 294 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 295 | @param host: string, the hostname or IP address of the bmc to log out of | 
|  | 296 | @param username: The user name for the bmc to log out of | 
|  | 297 | @param pw: The password for the BMC to log out of | 
|  | 298 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 299 | @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true. | 
|  | 300 | """ | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 301 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 302 | r = session.post('https://'+host+'/logout', headers=jsonHeader,json = {"data": [username, pw]}, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 303 | except(requests.exceptions.Timeout): | 
|  | 304 | print(connectionErrHandler(jsonFormat, "Timeout", None)) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 305 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 306 | if(jsonFormat==False): | 
| Matt Spinler | eae05b0 | 2019-01-24 12:59:34 -0600 | [diff] [blame] | 307 | if r.status_code == 200: | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 308 | print('User ' +username + ' has been logged out') | 
|  | 309 |  | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 310 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 311 | def fru(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 312 | """ | 
|  | 313 | prints out the system inventory. deprecated see fruPrint and fruList | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 314 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 315 | @param host: string, the hostname or IP address of the bmc | 
|  | 316 | @param args: contains additional arguments used by the fru sub command | 
|  | 317 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 318 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 319 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 320 | #url="https://"+host+"/org/openbmc/inventory/system/chassis/enumerate" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 321 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 322 | #print(url) | 
|  | 323 | #res = session.get(url, headers=httpHeader, verify=False) | 
|  | 324 | #print(res.text) | 
|  | 325 | #sample = res.text | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 326 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 327 | #inv_list = json.loads(sample)["data"] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 328 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 329 | url="https://"+host+"/xyz/openbmc_project/inventory/enumerate" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 330 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 331 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 332 | except(requests.exceptions.Timeout): | 
|  | 333 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 334 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 335 | sample = res.text | 
|  | 336 | #     inv_list.update(json.loads(sample)["data"]) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 337 | # | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 338 | #     #determine column width's | 
|  | 339 | #     colNames = ["FRU Name", "FRU Type", "Has Fault", "Is FRU", "Present", "Version"] | 
|  | 340 | #     colWidths = setColWidth(["FRU Name", "fru_type", "fault", "is_fru", "present", "version"], 6, inv_list, colNames) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 341 | # | 
|  | 342 | #     print("FRU Name".ljust(colWidths[0])+ "FRU Type".ljust(colWidths[1]) + "Has Fault".ljust(colWidths[2]) + "Is FRU".ljust(colWidths[3])+ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 343 | #           "Present".ljust(colWidths[4]) + "Version".ljust(colWidths[5])) | 
|  | 344 | #     format the output | 
|  | 345 | #     for key in sorted(inv_list.keys()): | 
|  | 346 | #         keyParts = key.split("/") | 
|  | 347 | #         isFRU = "True" if (inv_list[key]["is_fru"]==1) else "False" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 348 | # | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 349 | #         fruEntry = (keyParts[len(keyParts) - 1].ljust(colWidths[0]) + inv_list[key]["fru_type"].ljust(colWidths[1])+ | 
|  | 350 | #                inv_list[key]["fault"].ljust(colWidths[2])+isFRU.ljust(colWidths[3])+ | 
|  | 351 | #                inv_list[key]["present"].ljust(colWidths[4])+ inv_list[key]["version"].ljust(colWidths[5])) | 
|  | 352 | #         if(isTTY): | 
|  | 353 | #             if(inv_list[key]["is_fru"] == 1): | 
|  | 354 | #                 color = "green" | 
|  | 355 | #                 bold = True | 
|  | 356 | #             else: | 
|  | 357 | #                 color='black' | 
|  | 358 | #                 bold = False | 
|  | 359 | #             fruEntry = hilight(fruEntry, color, bold) | 
|  | 360 | #         print (fruEntry) | 
|  | 361 | return sample | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 362 |  | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 363 | def fruPrint(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 364 | """ | 
|  | 365 | prints out all inventory | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 366 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 367 | @param host: string, the hostname or IP address of the bmc | 
|  | 368 | @param args: contains additional arguments used by the fru sub command | 
|  | 369 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 370 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 371 | @return returns the total fru list. | 
|  | 372 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 373 | url="https://"+host+"/xyz/openbmc_project/inventory/enumerate" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 374 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 375 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 376 | except(requests.exceptions.Timeout): | 
|  | 377 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 378 |  | 
| Justin Thaler | 3a5771b | 2019-01-23 14:31:52 -0600 | [diff] [blame] | 379 | frulist={} | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 380 | #     print(res.text) | 
| Justin Thaler | 3a5771b | 2019-01-23 14:31:52 -0600 | [diff] [blame] | 381 | if res.status_code==200: | 
|  | 382 | frulist['Hardware'] = res.json()['data'] | 
|  | 383 | else: | 
|  | 384 | if not args.json: | 
|  | 385 | return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message']) | 
|  | 386 | else: | 
|  | 387 | return res.json() | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 388 | url="https://"+host+"/xyz/openbmc_project/software/enumerate" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 389 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 390 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 391 | except(requests.exceptions.Timeout): | 
|  | 392 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 393 | #     print(res.text) | 
| Justin Thaler | 3a5771b | 2019-01-23 14:31:52 -0600 | [diff] [blame] | 394 | if res.status_code==200: | 
|  | 395 | frulist['Software'] = res.json()['data'] | 
|  | 396 | else: | 
|  | 397 | if not args.json(): | 
|  | 398 | return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message']) | 
|  | 399 | else: | 
|  | 400 | return res.json() | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 401 | return frulist | 
|  | 402 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 403 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 404 | def fruList(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 405 | """ | 
|  | 406 | prints out all inventory or only a specific specified item | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 407 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 408 | @param host: string, the hostname or IP address of the bmc | 
|  | 409 | @param args: contains additional arguments used by the fru sub command | 
|  | 410 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 411 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 412 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 413 | if(args.items==True): | 
|  | 414 | return fruPrint(host, args, session) | 
|  | 415 | else: | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 416 | return fruPrint(host, args, session) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 417 |  | 
|  | 418 |  | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 419 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 420 | def fruStatus(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 421 | """ | 
|  | 422 | prints out the status of all FRUs | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 423 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 424 | @param host: string, the hostname or IP address of the bmc | 
|  | 425 | @param args: contains additional arguments used by the fru sub command | 
|  | 426 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 427 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 428 | """ | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 429 | url="https://"+host+"/xyz/openbmc_project/inventory/enumerate" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 430 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 431 | res = session.get(url, headers=jsonHeader, verify=False) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 432 | except(requests.exceptions.Timeout): | 
|  | 433 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 434 | #     print(res.text) | 
| Justin Thaler | 3a5771b | 2019-01-23 14:31:52 -0600 | [diff] [blame] | 435 | frulist = res.json()['data'] | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 436 | frus = {} | 
|  | 437 | for key in frulist: | 
|  | 438 | component = frulist[key] | 
|  | 439 | isFru = False | 
|  | 440 | present = False | 
|  | 441 | func = False | 
|  | 442 | hasSels = False | 
|  | 443 | keyPieces = key.split('/') | 
|  | 444 | fruName = keyPieces[-1] | 
|  | 445 | if 'core' in fruName: #associate cores to cpus | 
|  | 446 | fruName = keyPieces[-2] + '-' + keyPieces[-1] | 
|  | 447 | if 'Functional' in component: | 
|  | 448 | if('Present' in component): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 449 | if 'FieldReplaceable' in component: | 
|  | 450 | if component['FieldReplaceable'] == 1: | 
|  | 451 | isFru = True | 
|  | 452 | if "fan" in fruName: | 
|  | 453 | isFru = True; | 
|  | 454 | if component['Present'] == 1: | 
|  | 455 | present = True | 
|  | 456 | if component['Functional'] == 1: | 
|  | 457 | func = True | 
|  | 458 | if ((key + "/fault") in frulist): | 
|  | 459 | hasSels = True; | 
|  | 460 | if args.verbose: | 
|  | 461 | if hasSels: | 
|  | 462 | loglist = [] | 
|  | 463 | faults = frulist[key+"/fault"]['endpoints'] | 
|  | 464 | for item in faults: | 
|  | 465 | loglist.append(item.split('/')[-1]) | 
|  | 466 | frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() } | 
|  | 467 | else: | 
|  | 468 | frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" } | 
|  | 469 | else: | 
|  | 470 | frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) } | 
| Justin Thaler | fb9c81c | 2018-07-16 11:14:37 -0500 | [diff] [blame] | 471 | elif "power_supply" in fruName or "powersupply" in fruName: | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 472 | if component['Present'] ==1: | 
|  | 473 | present = True | 
|  | 474 | isFru = True | 
|  | 475 | if ((key + "/fault") in frulist): | 
|  | 476 | hasSels = True; | 
|  | 477 | if args.verbose: | 
|  | 478 | if hasSels: | 
|  | 479 | loglist = [] | 
|  | 480 | faults = frulist[key+"/fault"]['endpoints'] | 
| Obihörnchen | ff8035f | 2018-12-05 21:07:37 +0100 | [diff] [blame] | 481 | for item in faults: | 
|  | 482 | loglist.append(item.split('/')[-1]) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 483 | frus[fruName] = {"compName": fruName, "Functional": "No", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() } | 
|  | 484 | else: | 
|  | 485 | frus[fruName] = {"compName": fruName, "Functional": "Yes", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" } | 
|  | 486 | else: | 
|  | 487 | frus[fruName] = {"compName": fruName, "Functional": boolToString(not hasSels), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) } | 
|  | 488 | if not args.json: | 
|  | 489 | if not args.verbose: | 
|  | 490 | colNames = ["Component", "Is a FRU", "Present", "Functional", "Has Logs"] | 
|  | 491 | keylist = ["compName", "IsFru", "Present", "Functional", "hasSEL"] | 
|  | 492 | else: | 
|  | 493 | colNames = ["Component", "Is a FRU", "Present", "Functional", "Assoc. Log Number(s)"] | 
|  | 494 | keylist = ["compName", "IsFru", "Present", "Functional", "selList"] | 
|  | 495 | return tableDisplay(keylist, colNames, frus) | 
|  | 496 | else: | 
|  | 497 | return str(json.dumps(frus, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 498 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 499 | def sensor(host, args, session): | 
|  | 500 | """ | 
|  | 501 | prints out all sensors | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 502 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 503 | @param host: string, the hostname or IP address of the bmc | 
|  | 504 | @param args: contains additional arguments used by the sensor sub command | 
|  | 505 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 506 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 507 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 508 | url="https://"+host+"/xyz/openbmc_project/sensors/enumerate" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 509 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 510 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 511 | except(requests.exceptions.Timeout): | 
|  | 512 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 513 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 514 | #Get OCC status | 
|  | 515 | url="https://"+host+"/org/open_power/control/enumerate" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 516 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 517 | occres = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 518 | except(requests.exceptions.Timeout): | 
|  | 519 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 520 | if not args.json: | 
|  | 521 | colNames = ['sensor', 'type', 'units', 'value', 'target'] | 
| Justin Thaler | 3a5771b | 2019-01-23 14:31:52 -0600 | [diff] [blame] | 522 | sensors = res.json()["data"] | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 523 | output = {} | 
|  | 524 | for key in sensors: | 
|  | 525 | senDict = {} | 
|  | 526 | keyparts = key.split("/") | 
|  | 527 | senDict['sensorName'] = keyparts[-1] | 
|  | 528 | senDict['type'] = keyparts[-2] | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 529 | try: | 
|  | 530 | senDict['units'] = sensors[key]['Unit'].split('.')[-1] | 
|  | 531 | except KeyError: | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 532 | senDict['units'] = "N/A" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 533 | if('Scale' in sensors[key]): | 
|  | 534 | scale = 10 ** sensors[key]['Scale'] | 
|  | 535 | else: | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 536 | scale = 1 | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 537 | try: | 
|  | 538 | senDict['value'] = str(sensors[key]['Value'] * scale) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 539 | except KeyError: | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 540 | if 'value' in sensors[key]: | 
|  | 541 | senDict['value'] = sensors[key]['value'] | 
|  | 542 | else: | 
|  | 543 | senDict['value'] = "N/A" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 544 | if 'Target' in sensors[key]: | 
|  | 545 | senDict['target'] = str(sensors[key]['Target']) | 
|  | 546 | else: | 
|  | 547 | senDict['target'] = 'N/A' | 
|  | 548 | output[senDict['sensorName']] = senDict | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 549 |  | 
| Justin Thaler | 3a5771b | 2019-01-23 14:31:52 -0600 | [diff] [blame] | 550 | occstatus = occres.json()["data"] | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 551 | if '/org/open_power/control/occ0' in occstatus: | 
|  | 552 | occ0 = occstatus["/org/open_power/control/occ0"]['OccActive'] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 553 | if occ0 == 1: | 
|  | 554 | occ0 = 'Active' | 
|  | 555 | else: | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 556 | occ0 = 'Inactive' | 
|  | 557 | output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'} | 
|  | 558 | occ1 = occstatus["/org/open_power/control/occ1"]['OccActive'] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 559 | if occ1 == 1: | 
|  | 560 | occ1 = 'Active' | 
|  | 561 | else: | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 562 | occ1 = 'Inactive' | 
|  | 563 | output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'} | 
|  | 564 | else: | 
|  | 565 | output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'} | 
|  | 566 | output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'} | 
|  | 567 | keylist = ['sensorName', 'type', 'units', 'value', 'target'] | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 568 |  | 
|  | 569 | return tableDisplay(keylist, colNames, output) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 570 | else: | 
|  | 571 | return res.text + occres.text | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 572 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 573 | def sel(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 574 | """ | 
|  | 575 | prints out the bmc alerts | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 576 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 577 | @param host: string, the hostname or IP address of the bmc | 
|  | 578 | @param args: contains additional arguments used by the sel sub command | 
|  | 579 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 580 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 581 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 582 |  | 
|  | 583 | url="https://"+host+"/xyz/openbmc_project/logging/entry/enumerate" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 584 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 585 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 586 | except(requests.exceptions.Timeout): | 
|  | 587 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 588 | return res.text | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 589 |  | 
|  | 590 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 591 | def parseESEL(args, eselRAW): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 592 | """ | 
|  | 593 | parses the esel data and gets predetermined search terms | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 594 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 595 | @param eselRAW: string, the raw esel string from the bmc | 
|  | 596 | @return: A dictionary containing the quick snapshot data unless args.fullEsel is listed then a full PEL log is returned | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 597 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 598 | eselParts = {} | 
|  | 599 | esel_bin = binascii.unhexlify(''.join(eselRAW.split()[16:])) | 
|  | 600 | #search terms contains the search term as the key and the return dictionary key as it's value | 
|  | 601 | searchTerms = { 'Signature Description':'signatureDescription', 'devdesc':'devdesc', | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 602 | 'Callout type': 'calloutType', 'Procedure':'procedure', 'Sensor Type': 'sensorType'} | 
| Justin Thaler | 24d4efa | 2018-11-08 22:48:10 -0600 | [diff] [blame] | 603 | uniqueID = str(uuid.uuid4()) | 
|  | 604 | eselBinPath = tempfile.gettempdir() + os.sep + uniqueID + 'esel.bin' | 
| Justin Thaler | cf1deae | 2018-05-25 19:35:21 -0500 | [diff] [blame] | 605 | with open(eselBinPath, 'wb') as f: | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 606 | f.write(esel_bin) | 
|  | 607 | errlPath = "" | 
|  | 608 | #use the right errl file for the machine architecture | 
|  | 609 | arch = platform.machine() | 
|  | 610 | if(arch =='x86_64' or arch =='AMD64'): | 
|  | 611 | if os.path.exists('/opt/ibm/ras/bin/x86_64/errl'): | 
|  | 612 | errlPath = '/opt/ibm/ras/bin/x86_64/errl' | 
|  | 613 | elif os.path.exists('errl/x86_64/errl'): | 
|  | 614 | errlPath = 'errl/x86_64/errl' | 
|  | 615 | else: | 
|  | 616 | errlPath = 'x86_64/errl' | 
|  | 617 | elif (platform.machine()=='ppc64le'): | 
|  | 618 | if os.path.exists('/opt/ibm/ras/bin/ppc64le/errl'): | 
|  | 619 | errlPath = '/opt/ibm/ras/bin/ppc64le/errl' | 
|  | 620 | elif os.path.exists('errl/ppc64le/errl'): | 
|  | 621 | errlPath = 'errl/ppc64le/errl' | 
|  | 622 | else: | 
|  | 623 | errlPath = 'ppc64le/errl' | 
|  | 624 | else: | 
|  | 625 | print("machine architecture not supported for parsing eSELs") | 
|  | 626 | return eselParts | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 627 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 628 | if(os.path.exists(errlPath)): | 
| Justin Thaler | cf1deae | 2018-05-25 19:35:21 -0500 | [diff] [blame] | 629 | output= subprocess.check_output([errlPath, '-d', '--file='+eselBinPath]).decode('utf-8') | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 630 | #         output = proc.communicate()[0] | 
|  | 631 | lines = output.split('\n') | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 632 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 633 | if(hasattr(args, 'fullEsel')): | 
|  | 634 | return output | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 635 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 636 | for i in range(0, len(lines)): | 
|  | 637 | lineParts = lines[i].split(':') | 
|  | 638 | if(len(lineParts)>1): #ignore multi lines, output formatting lines, and other information | 
|  | 639 | for term in searchTerms: | 
|  | 640 | if(term in lineParts[0]): | 
|  | 641 | temp = lines[i][lines[i].find(':')+1:].strip()[:-1].strip() | 
|  | 642 | if lines[i+1].find(':') != -1: | 
|  | 643 | if (len(lines[i+1].split(':')[0][1:].strip())==0): | 
|  | 644 | while(len(lines[i][:lines[i].find(':')].strip())>2): | 
| Justin Thaler | 4303042 | 2018-11-08 22:50:21 -0600 | [diff] [blame] | 645 | #has multiple lines, process and update line counter | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 646 | if((i+1) <= len(lines)): | 
|  | 647 | i+=1 | 
|  | 648 | else: | 
|  | 649 | i=i-1 | 
|  | 650 | break | 
| Justin Thaler | 4303042 | 2018-11-08 22:50:21 -0600 | [diff] [blame] | 651 | #Append the content from the next line removing the pretty display characters | 
|  | 652 | #Finds the first colon then starts 2 characters after, then removes all whitespace | 
|  | 653 | temp = temp + lines[i][lines[i].find(':')+2:].strip()[:-1].strip()[:-1].strip() | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 654 | if(searchTerms[term] in eselParts): | 
|  | 655 | eselParts[searchTerms[term]] = eselParts[searchTerms[term]] + ", " + temp | 
|  | 656 | else: | 
|  | 657 | eselParts[searchTerms[term]] = temp | 
| Justin Thaler | cf1deae | 2018-05-25 19:35:21 -0500 | [diff] [blame] | 658 | os.remove(eselBinPath) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 659 | else: | 
|  | 660 | print("errl file cannot be found") | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 661 |  | 
|  | 662 | return eselParts | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 663 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 664 |  | 
| Matt Spinler | 02d0dff | 2018-08-29 13:19:25 -0500 | [diff] [blame] | 665 | def getESELSeverity(esel): | 
|  | 666 | """ | 
|  | 667 | Finds the severity type in an eSEL from the User Header section. | 
|  | 668 | @param esel - the eSEL data | 
|  | 669 | @return severity - e.g. 'Critical' | 
|  | 670 | """ | 
|  | 671 |  | 
|  | 672 | # everything but 1 and 2 are Critical | 
|  | 673 | # '1': 'recovered', | 
|  | 674 | # '2': 'predictive', | 
|  | 675 | # '4': 'unrecoverable', | 
|  | 676 | # '5': 'critical', | 
|  | 677 | # '6': 'diagnostic', | 
|  | 678 | # '7': 'symptom' | 
|  | 679 | severities = { | 
|  | 680 | '1': 'Informational', | 
|  | 681 | '2': 'Warning' | 
|  | 682 | } | 
|  | 683 |  | 
|  | 684 | try: | 
|  | 685 | headerPosition = esel.index('55 48') # 'UH' | 
|  | 686 | # The severity is the last byte in the 8 byte section (a byte is '  bb') | 
|  | 687 | severity = esel[headerPosition:headerPosition+32].split(' ')[-1] | 
|  | 688 | type = severity[0] | 
|  | 689 | except ValueError: | 
|  | 690 | print("Could not find severity value in UH section in eSEL") | 
|  | 691 | type = 'x'; | 
|  | 692 |  | 
|  | 693 | return severities.get(type, 'Critical') | 
|  | 694 |  | 
|  | 695 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 696 | def sortSELs(events): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 697 | """ | 
|  | 698 | sorts the sels by timestamp, then log entry number | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 699 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 700 | @param events: Dictionary containing events | 
|  | 701 | @return: list containing a list of the ordered log entries, and dictionary of keys | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 702 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 703 | logNumList = [] | 
|  | 704 | timestampList = [] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 705 | eventKeyDict = {} | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 706 | eventsWithTimestamp = {} | 
|  | 707 | logNum2events = {} | 
|  | 708 | for key in events: | 
|  | 709 | if key == 'numAlerts': continue | 
|  | 710 | if 'callout' in key: continue | 
|  | 711 | timestamp = (events[key]['timestamp']) | 
|  | 712 | if timestamp not in timestampList: | 
|  | 713 | eventsWithTimestamp[timestamp] = [events[key]['logNum']] | 
|  | 714 | else: | 
|  | 715 | eventsWithTimestamp[timestamp].append(events[key]['logNum']) | 
|  | 716 | #map logNumbers to the event dictionary keys | 
|  | 717 | eventKeyDict[str(events[key]['logNum'])] = key | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 718 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 719 | timestampList = list(eventsWithTimestamp.keys()) | 
|  | 720 | timestampList.sort() | 
|  | 721 | for ts in timestampList: | 
|  | 722 | if len(eventsWithTimestamp[ts]) > 1: | 
|  | 723 | tmplist = eventsWithTimestamp[ts] | 
|  | 724 | tmplist.sort() | 
|  | 725 | logNumList = logNumList + tmplist | 
|  | 726 | else: | 
|  | 727 | logNumList = logNumList + eventsWithTimestamp[ts] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 728 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 729 | return [logNumList, eventKeyDict] | 
|  | 730 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 731 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 732 | def parseAlerts(policyTable, selEntries, args): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 733 | """ | 
|  | 734 | parses alerts in the IBM CER format, using an IBM policy Table | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 735 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 736 | @param policyTable: dictionary, the policy table entries | 
|  | 737 | @param selEntries: dictionary, the alerts retrieved from the bmc | 
|  | 738 | @return: A dictionary of the parsed entries, in chronological order | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 739 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 740 | eventDict = {} | 
|  | 741 | eventNum ="" | 
|  | 742 | count = 0 | 
|  | 743 | esel = "" | 
|  | 744 | eselParts = {} | 
|  | 745 | i2cdevice= "" | 
| Matt Spinler | 02d0dff | 2018-08-29 13:19:25 -0500 | [diff] [blame] | 746 | eselSeverity = None | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 747 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 748 | 'prepare and sort the event entries' | 
|  | 749 | for key in selEntries: | 
|  | 750 | if 'callout' not in key: | 
|  | 751 | selEntries[key]['logNum'] = key.split('/')[-1] | 
|  | 752 | selEntries[key]['timestamp'] = selEntries[key]['Timestamp'] | 
|  | 753 | sortedEntries = sortSELs(selEntries) | 
|  | 754 | logNumList = sortedEntries[0] | 
|  | 755 | eventKeyDict = sortedEntries[1] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 756 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 757 | for logNum in logNumList: | 
|  | 758 | key = eventKeyDict[logNum] | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 759 | hasEsel=False | 
|  | 760 | i2creadFail = False | 
|  | 761 | if 'callout' in key: | 
|  | 762 | continue | 
|  | 763 | else: | 
|  | 764 | messageID = str(selEntries[key]['Message']) | 
|  | 765 | addDataPiece = selEntries[key]['AdditionalData'] | 
|  | 766 | calloutIndex = 0 | 
|  | 767 | calloutFound = False | 
|  | 768 | for i in range(len(addDataPiece)): | 
|  | 769 | if("CALLOUT_INVENTORY_PATH" in addDataPiece[i]): | 
|  | 770 | calloutIndex = i | 
|  | 771 | calloutFound = True | 
|  | 772 | fruCallout = str(addDataPiece[calloutIndex]).split('=')[1] | 
|  | 773 | if("CALLOUT_DEVICE_PATH" in addDataPiece[i]): | 
|  | 774 | i2creadFail = True | 
| Matt Spinler | d178a47 | 2018-08-31 09:48:52 -0500 | [diff] [blame] | 775 |  | 
|  | 776 | fruCallout = str(addDataPiece[calloutIndex]).split('=')[1] | 
|  | 777 |  | 
|  | 778 | # Fall back to "I2C"/"FSI" if dev path isn't in policy table | 
|  | 779 | if (messageID + '||' + fruCallout) not in policyTable: | 
|  | 780 | i2cdevice = str(addDataPiece[i]).strip().split('=')[1] | 
|  | 781 | i2cdevice = '/'.join(i2cdevice.split('/')[-4:]) | 
|  | 782 | if 'fsi' in str(addDataPiece[calloutIndex]).split('=')[1]: | 
|  | 783 | fruCallout = 'FSI' | 
|  | 784 | else: | 
|  | 785 | fruCallout = 'I2C' | 
| Justin Thaler | e34c43a | 2018-05-25 19:37:55 -0500 | [diff] [blame] | 786 | calloutFound = True | 
|  | 787 | if("CALLOUT_GPIO_NUM" in addDataPiece[i]): | 
|  | 788 | if not calloutFound: | 
|  | 789 | fruCallout = 'GPIO' | 
|  | 790 | calloutFound = True | 
|  | 791 | if("CALLOUT_IIC_BUS" in addDataPiece[i]): | 
|  | 792 | if not calloutFound: | 
|  | 793 | fruCallout = "I2C" | 
|  | 794 | calloutFound = True | 
|  | 795 | if("CALLOUT_IPMI_SENSOR_NUM" in addDataPiece[i]): | 
|  | 796 | if not calloutFound: | 
|  | 797 | fruCallout = "IPMI" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 798 | calloutFound = True | 
|  | 799 | if("ESEL" in addDataPiece[i]): | 
|  | 800 | esel = str(addDataPiece[i]).strip().split('=')[1] | 
| Matt Spinler | 02d0dff | 2018-08-29 13:19:25 -0500 | [diff] [blame] | 801 | eselSeverity = getESELSeverity(esel) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 802 | if args.devdebug: | 
|  | 803 | eselParts = parseESEL(args, esel) | 
|  | 804 | hasEsel=True | 
|  | 805 | if("GPU" in addDataPiece[i]): | 
|  | 806 | fruCallout = '/xyz/openbmc_project/inventory/system/chassis/motherboard/gpu' + str(addDataPiece[i]).strip()[-1] | 
|  | 807 | calloutFound = True | 
|  | 808 | if("PROCEDURE" in addDataPiece[i]): | 
|  | 809 | fruCallout = str(hex(int(str(addDataPiece[i]).split('=')[1])))[2:] | 
|  | 810 | calloutFound = True | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 811 | if("RAIL_NAME" in addDataPiece[i]): | 
|  | 812 | calloutFound=True | 
|  | 813 | fruCallout = str(addDataPiece[i]).split('=')[1].strip() | 
|  | 814 | if("INPUT_NAME" in addDataPiece[i]): | 
|  | 815 | calloutFound=True | 
|  | 816 | fruCallout = str(addDataPiece[i]).split('=')[1].strip() | 
|  | 817 | if("SENSOR_TYPE" in addDataPiece[i]): | 
|  | 818 | calloutFound=True | 
|  | 819 | fruCallout = str(addDataPiece[i]).split('=')[1].strip() | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 820 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 821 | if(calloutFound): | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 822 | if fruCallout != "": | 
|  | 823 | policyKey = messageID +"||" +  fruCallout | 
| Matt Spinler | 02d0dff | 2018-08-29 13:19:25 -0500 | [diff] [blame] | 824 |  | 
|  | 825 | # Also use the severity for hostboot errors | 
|  | 826 | if eselSeverity and messageID == 'org.open_power.Host.Error.Event': | 
|  | 827 | policyKey += '||' + eselSeverity | 
|  | 828 |  | 
|  | 829 | # if not in the table, fall back to the original key | 
|  | 830 | if policyKey not in policyTable: | 
|  | 831 | policyKey = policyKey.replace('||'+eselSeverity, '') | 
|  | 832 |  | 
| Justin Thaler | e34c43a | 2018-05-25 19:37:55 -0500 | [diff] [blame] | 833 | if policyKey not in policyTable: | 
|  | 834 | policyKey = messageID | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 835 | else: | 
|  | 836 | policyKey = messageID | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 837 | else: | 
|  | 838 | policyKey = messageID | 
|  | 839 | event = {} | 
|  | 840 | eventNum = str(count) | 
|  | 841 | if policyKey in policyTable: | 
|  | 842 | for pkey in policyTable[policyKey]: | 
|  | 843 | if(type(policyTable[policyKey][pkey])== bool): | 
|  | 844 | event[pkey] = boolToString(policyTable[policyKey][pkey]) | 
|  | 845 | else: | 
|  | 846 | if (i2creadFail and pkey == 'Message'): | 
|  | 847 | event[pkey] = policyTable[policyKey][pkey] + ' ' +i2cdevice | 
|  | 848 | else: | 
|  | 849 | event[pkey] = policyTable[policyKey][pkey] | 
|  | 850 | event['timestamp'] = selEntries[key]['Timestamp'] | 
|  | 851 | event['resolved'] = bool(selEntries[key]['Resolved']) | 
|  | 852 | if(hasEsel): | 
|  | 853 | if args.devdebug: | 
|  | 854 | event['eselParts'] = eselParts | 
|  | 855 | event['raweSEL'] = esel | 
|  | 856 | event['logNum'] = key.split('/')[-1] | 
|  | 857 | eventDict['event' + eventNum] = event | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 858 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 859 | else: | 
|  | 860 | severity = str(selEntries[key]['Severity']).split('.')[-1] | 
|  | 861 | if severity == 'Error': | 
|  | 862 | severity = 'Critical' | 
|  | 863 | eventDict['event'+eventNum] = {} | 
|  | 864 | eventDict['event' + eventNum]['error'] = "error: Not found in policy table: " + policyKey | 
|  | 865 | eventDict['event' + eventNum]['timestamp'] = selEntries[key]['Timestamp'] | 
|  | 866 | eventDict['event' + eventNum]['Severity'] = severity | 
|  | 867 | if(hasEsel): | 
|  | 868 | if args.devdebug: | 
|  | 869 | eventDict['event' +eventNum]['eselParts'] = eselParts | 
|  | 870 | eventDict['event' +eventNum]['raweSEL'] = esel | 
|  | 871 | eventDict['event' +eventNum]['logNum'] = key.split('/')[-1] | 
|  | 872 | eventDict['event' +eventNum]['resolved'] = bool(selEntries[key]['Resolved']) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 873 | count += 1 | 
|  | 874 | return eventDict | 
|  | 875 |  | 
|  | 876 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 877 | def selDisplay(events, args): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 878 | """ | 
|  | 879 | displays alerts in human readable format | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 880 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 881 | @param events: Dictionary containing events | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 882 | @return: | 
|  | 883 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 884 | activeAlerts = [] | 
|  | 885 | historyAlerts = [] | 
|  | 886 | sortedEntries = sortSELs(events) | 
|  | 887 | logNumList = sortedEntries[0] | 
|  | 888 | eventKeyDict = sortedEntries[1] | 
|  | 889 | keylist = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message'] | 
|  | 890 | if(args.devdebug): | 
|  | 891 | colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message',  'eSEL contents'] | 
|  | 892 | keylist.append('eSEL') | 
|  | 893 | else: | 
|  | 894 | colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity', 'Message'] | 
|  | 895 | for log in logNumList: | 
|  | 896 | selDict = {} | 
|  | 897 | alert = events[eventKeyDict[str(log)]] | 
|  | 898 | if('error' in alert): | 
|  | 899 | selDict['Entry'] = alert['logNum'] | 
|  | 900 | selDict['ID'] = 'Unknown' | 
|  | 901 | selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S") | 
|  | 902 | msg = alert['error'] | 
|  | 903 | polMsg = msg.split("policy table:")[0] | 
|  | 904 | msg = msg.split("policy table:")[1] | 
|  | 905 | msgPieces = msg.split("||") | 
|  | 906 | err = msgPieces[0] | 
|  | 907 | if(err.find("org.open_power.")!=-1): | 
|  | 908 | err = err.split("org.open_power.")[1] | 
|  | 909 | elif(err.find("xyz.openbmc_project.")!=-1): | 
|  | 910 | err = err.split("xyz.openbmc_project.")[1] | 
|  | 911 | else: | 
|  | 912 | err = msgPieces[0] | 
|  | 913 | callout = "" | 
|  | 914 | if len(msgPieces) >1: | 
|  | 915 | callout = msgPieces[1] | 
|  | 916 | if(callout.find("/org/open_power/")!=-1): | 
|  | 917 | callout = callout.split("/org/open_power/")[1] | 
|  | 918 | elif(callout.find("/xyz/openbmc_project/")!=-1): | 
|  | 919 | callout = callout.split("/xyz/openbmc_project/")[1] | 
|  | 920 | else: | 
|  | 921 | callout = msgPieces[1] | 
|  | 922 | selDict['Message'] = polMsg +"policy table: "+ err +  "||" + callout | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 923 | selDict['Serviceable'] = 'Unknown' | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 924 | selDict['Severity'] = alert['Severity'] | 
|  | 925 | else: | 
|  | 926 | selDict['Entry'] = alert['logNum'] | 
|  | 927 | selDict['ID'] = alert['CommonEventID'] | 
|  | 928 | selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S") | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 929 | selDict['Message'] = alert['Message'] | 
|  | 930 | selDict['Serviceable'] = alert['Serviceable'] | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 931 | selDict['Severity'] = alert['Severity'] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 932 |  | 
|  | 933 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 934 | eselOrder = ['refCode','signatureDescription', 'eselType', 'devdesc', 'calloutType', 'procedure'] | 
|  | 935 | if ('eselParts' in alert and args.devdebug): | 
|  | 936 | eselOutput = "" | 
|  | 937 | for item in eselOrder: | 
|  | 938 | if item in alert['eselParts']: | 
|  | 939 | eselOutput = eselOutput + item + ": " + alert['eselParts'][item] + " | " | 
|  | 940 | selDict['eSEL'] = eselOutput | 
|  | 941 | else: | 
|  | 942 | if args.devdebug: | 
|  | 943 | selDict['eSEL'] = "None" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 944 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 945 | if not alert['resolved']: | 
|  | 946 | activeAlerts.append(selDict) | 
|  | 947 | else: | 
|  | 948 | historyAlerts.append(selDict) | 
|  | 949 | mergedOutput = activeAlerts + historyAlerts | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 950 | colWidth = setColWidth(keylist, len(colNames), dict(enumerate(mergedOutput)), colNames) | 
|  | 951 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 952 | output = "" | 
|  | 953 | if(len(activeAlerts)>0): | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 954 | row = "" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 955 | output +="----Active Alerts----\n" | 
|  | 956 | for i in range(0, len(colNames)): | 
|  | 957 | if i!=0: row =row + "| " | 
|  | 958 | row = row + colNames[i].ljust(colWidth[i]) | 
|  | 959 | output += row + "\n" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 960 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 961 | for i in range(0,len(activeAlerts)): | 
|  | 962 | row = "" | 
|  | 963 | for j in range(len(activeAlerts[i])): | 
|  | 964 | if (j != 0): row = row + "| " | 
|  | 965 | row = row + activeAlerts[i][keylist[j]].ljust(colWidth[j]) | 
|  | 966 | output += row + "\n" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 967 |  | 
|  | 968 | if(len(historyAlerts)>0): | 
|  | 969 | row = "" | 
|  | 970 | output+= "----Historical Alerts----\n" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 971 | for i in range(len(colNames)): | 
|  | 972 | if i!=0: row =row + "| " | 
|  | 973 | row = row + colNames[i].ljust(colWidth[i]) | 
|  | 974 | output += row + "\n" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 975 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 976 | for i in range(0, len(historyAlerts)): | 
|  | 977 | row = "" | 
|  | 978 | for j in range(len(historyAlerts[i])): | 
|  | 979 | if (j != 0): row = row + "| " | 
|  | 980 | row = row + historyAlerts[i][keylist[j]].ljust(colWidth[j]) | 
|  | 981 | output += row + "\n" | 
|  | 982 | #         print(events[eventKeyDict[str(log)]]) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 983 | return output | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 984 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 985 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 986 | def selPrint(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 987 | """ | 
|  | 988 | prints out all bmc alerts | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 989 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 990 | @param host: string, the hostname or IP address of the bmc | 
|  | 991 | @param args: contains additional arguments used by the fru sub command | 
|  | 992 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 993 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 994 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 995 | if(args.policyTableLoc is None): | 
|  | 996 | if os.path.exists('policyTable.json'): | 
|  | 997 | ptableLoc = "policyTable.json" | 
|  | 998 | elif os.path.exists('/opt/ibm/ras/lib/policyTable.json'): | 
|  | 999 | ptableLoc = '/opt/ibm/ras/lib/policyTable.json' | 
|  | 1000 | else: | 
|  | 1001 | ptableLoc = 'lib/policyTable.json' | 
|  | 1002 | else: | 
|  | 1003 | ptableLoc = args.policyTableLoc | 
|  | 1004 | policyTable = loadPolicyTable(ptableLoc) | 
|  | 1005 | rawselEntries = "" | 
|  | 1006 | if(hasattr(args, 'fileloc') and args.fileloc is not None): | 
|  | 1007 | if os.path.exists(args.fileloc): | 
|  | 1008 | with open(args.fileloc, 'r') as selFile: | 
|  | 1009 | selLines = selFile.readlines() | 
|  | 1010 | rawselEntries = ''.join(selLines) | 
|  | 1011 | else: | 
|  | 1012 | print("Error: File not found") | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1013 | sys.exit(1) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1014 | else: | 
|  | 1015 | rawselEntries = sel(host, args, session) | 
|  | 1016 | loadFailed = False | 
|  | 1017 | try: | 
|  | 1018 | selEntries = json.loads(rawselEntries) | 
|  | 1019 | except ValueError: | 
|  | 1020 | loadFailed = True | 
|  | 1021 | if loadFailed: | 
|  | 1022 | cleanSels = json.dumps(rawselEntries).replace('\\n', '') | 
|  | 1023 | #need to load json twice as original content was string escaped a second time | 
|  | 1024 | selEntries = json.loads(json.loads(cleanSels)) | 
|  | 1025 | selEntries = selEntries['data'] | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1026 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1027 | if 'description' in selEntries: | 
|  | 1028 | if(args.json): | 
|  | 1029 | return("{\n\t\"numAlerts\": 0\n}") | 
|  | 1030 | else: | 
|  | 1031 | return("No log entries found") | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1032 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1033 | else: | 
|  | 1034 | if(len(policyTable)>0): | 
|  | 1035 | events = parseAlerts(policyTable, selEntries, args) | 
|  | 1036 | if(args.json): | 
|  | 1037 | events["numAlerts"] = len(events) | 
|  | 1038 | retValue = str(json.dumps(events, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)) | 
|  | 1039 | return retValue | 
|  | 1040 | elif(hasattr(args, 'fullSel')): | 
|  | 1041 | return events | 
|  | 1042 | else: | 
|  | 1043 | #get log numbers to order event entries sequentially | 
|  | 1044 | return selDisplay(events, args) | 
|  | 1045 | else: | 
|  | 1046 | if(args.json): | 
|  | 1047 | return selEntries | 
|  | 1048 | else: | 
|  | 1049 | print("error: Policy Table not found.") | 
|  | 1050 | return selEntries | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1051 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1052 | def selList(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1053 | """ | 
|  | 1054 | prints out all all bmc alerts, or only prints out the specified alerts | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1055 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1056 | @param host: string, the hostname or IP address of the bmc | 
|  | 1057 | @param args: contains additional arguments used by the fru sub command | 
|  | 1058 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1059 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1060 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1061 | return(sel(host, args, session)) | 
|  | 1062 |  | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1063 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1064 | def selClear(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1065 | """ | 
|  | 1066 | clears all alerts | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1067 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1068 | @param host: string, the hostname or IP address of the bmc | 
|  | 1069 | @param args: contains additional arguments used by the fru sub command | 
|  | 1070 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1071 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1072 | """ | 
| Matt Spinler | 47b13e9 | 2019-01-04 14:58:53 -0600 | [diff] [blame] | 1073 | url="https://"+host+"/xyz/openbmc_project/logging/action/DeleteAll" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1074 | data = "{\"data\": [] }" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1075 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1076 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1077 | res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1078 | except(requests.exceptions.Timeout): | 
|  | 1079 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1080 | if res.status_code == 200: | 
|  | 1081 | return "The Alert Log has been cleared. Please allow a few minutes for the action to complete." | 
|  | 1082 | else: | 
|  | 1083 | print("Unable to clear the logs, trying to clear 1 at a time") | 
|  | 1084 | sels = json.loads(sel(host, args, session))['data'] | 
|  | 1085 | for key in sels: | 
|  | 1086 | if 'callout' not in key: | 
|  | 1087 | logNum = key.split('/')[-1] | 
|  | 1088 | url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete" | 
|  | 1089 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1090 | session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1091 | except(requests.exceptions.Timeout): | 
|  | 1092 | return connectionErrHandler(args.json, "Timeout", None) | 
|  | 1093 | sys.exit(1) | 
|  | 1094 | except(requests.exceptions.ConnectionError) as err: | 
|  | 1095 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 1096 | sys.exit(1) | 
|  | 1097 | return ('Sel clearing complete') | 
|  | 1098 |  | 
|  | 1099 | def selSetResolved(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1100 | """ | 
|  | 1101 | sets a sel entry to resolved | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1102 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1103 | @param host: string, the hostname or IP address of the bmc | 
|  | 1104 | @param args: contains additional arguments used by the fru sub command | 
|  | 1105 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1106 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1107 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1108 | url="https://"+host+"/xyz/openbmc_project/logging/entry/" + str(args.selNum) + "/attr/Resolved" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1109 | data = "{\"data\": 1 }" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1110 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1111 | res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1112 | except(requests.exceptions.Timeout): | 
|  | 1113 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1114 | if res.status_code == 200: | 
|  | 1115 | return "Sel entry "+ str(args.selNum) +" is now set to resolved" | 
|  | 1116 | else: | 
|  | 1117 | return "Unable to set the alert to resolved" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1118 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1119 | def selResolveAll(host, args, session): | 
|  | 1120 | """ | 
|  | 1121 | sets a sel entry to resolved | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1122 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1123 | @param host: string, the hostname or IP address of the bmc | 
|  | 1124 | @param args: contains additional arguments used by the fru sub command | 
|  | 1125 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1126 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1127 | """ | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1128 | rawselEntries = sel(host, args, session) | 
|  | 1129 | loadFailed = False | 
|  | 1130 | try: | 
|  | 1131 | selEntries = json.loads(rawselEntries) | 
|  | 1132 | except ValueError: | 
|  | 1133 | loadFailed = True | 
|  | 1134 | if loadFailed: | 
|  | 1135 | cleanSels = json.dumps(rawselEntries).replace('\\n', '') | 
|  | 1136 | #need to load json twice as original content was string escaped a second time | 
|  | 1137 | selEntries = json.loads(json.loads(cleanSels)) | 
|  | 1138 | selEntries = selEntries['data'] | 
|  | 1139 |  | 
|  | 1140 | if 'description' in selEntries: | 
|  | 1141 | if(args.json): | 
|  | 1142 | return("{\n\t\"selsResolved\": 0\n}") | 
|  | 1143 | else: | 
|  | 1144 | return("No log entries found") | 
|  | 1145 | else: | 
|  | 1146 | d = vars(args) | 
|  | 1147 | successlist = [] | 
|  | 1148 | failedlist = [] | 
|  | 1149 | for key in selEntries: | 
|  | 1150 | if 'callout' not in key: | 
|  | 1151 | d['selNum'] = key.split('/')[-1] | 
|  | 1152 | resolved = selSetResolved(host,args,session) | 
|  | 1153 | if 'Sel entry' in resolved: | 
|  | 1154 | successlist.append(d['selNum']) | 
|  | 1155 | else: | 
|  | 1156 | failedlist.append(d['selNum']) | 
|  | 1157 | output = "" | 
|  | 1158 | successlist.sort() | 
|  | 1159 | failedlist.sort() | 
|  | 1160 | if len(successlist)>0: | 
|  | 1161 | output = "Successfully resolved: " +', '.join(successlist) +"\n" | 
|  | 1162 | if len(failedlist)>0: | 
|  | 1163 | output += "Failed to resolve: " + ', '.join(failedlist) + "\n" | 
|  | 1164 | return output | 
|  | 1165 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1166 | def chassisPower(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1167 | """ | 
|  | 1168 | called by the chassis function. Controls the power state of the chassis, or gets the status | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1169 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1170 | @param host: string, the hostname or IP address of the bmc | 
|  | 1171 | @param args: contains additional arguments used by the fru sub command | 
|  | 1172 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1173 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1174 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1175 | if(args.powcmd == 'on'): | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 1176 | if checkFWactivation(host, args, session): | 
|  | 1177 | return ("Chassis Power control disabled during firmware activation") | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1178 | print("Attempting to Power on...:") | 
|  | 1179 | url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1180 | data = '{"data":"xyz.openbmc_project.State.Host.Transition.On"}' | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1181 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1182 | res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1183 | except(requests.exceptions.Timeout): | 
|  | 1184 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1185 | return res.text | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1186 | elif(args.powcmd == 'softoff'): | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 1187 | if checkFWactivation(host, args, session): | 
|  | 1188 | return ("Chassis Power control disabled during firmware activation") | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1189 | print("Attempting to Power off gracefully...:") | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1190 | url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1191 | data = '{"data":"xyz.openbmc_project.State.Host.Transition.Off"}' | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1192 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1193 | res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1194 | except(requests.exceptions.Timeout): | 
|  | 1195 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 1196 | return res.text | 
|  | 1197 | elif(args.powcmd == 'hardoff'): | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 1198 | if checkFWactivation(host, args, session): | 
|  | 1199 | return ("Chassis Power control disabled during firmware activation") | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1200 | print("Attempting to Power off immediately...:") | 
|  | 1201 | url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1202 | data = '{"data":"xyz.openbmc_project.State.Chassis.Transition.Off"}' | 
|  | 1203 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1204 | res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1205 | except(requests.exceptions.Timeout): | 
|  | 1206 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1207 | return res.text | 
|  | 1208 | elif(args.powcmd == 'status'): | 
|  | 1209 | url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1210 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1211 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1212 | except(requests.exceptions.Timeout): | 
|  | 1213 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1214 | chassisState = json.loads(res.text)['data'].split('.')[-1] | 
|  | 1215 | url="https://"+host+"/xyz/openbmc_project/state/host0/attr/CurrentHostState" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1216 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1217 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1218 | except(requests.exceptions.Timeout): | 
|  | 1219 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1220 | hostState = json.loads(res.text)['data'].split('.')[-1] | 
|  | 1221 | url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/CurrentBMCState" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1222 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1223 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1224 | except(requests.exceptions.Timeout): | 
|  | 1225 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1226 | bmcState = json.loads(res.text)['data'].split('.')[-1] | 
|  | 1227 | if(args.json): | 
|  | 1228 | outDict = {"Chassis Power State" : chassisState, "Host Power State" : hostState, "BMC Power State":bmcState} | 
|  | 1229 | return json.dumps(outDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) | 
|  | 1230 | else: | 
|  | 1231 | return "Chassis Power State: " +chassisState + "\nHost Power State: " + hostState + "\nBMC Power State: " + bmcState | 
|  | 1232 | else: | 
|  | 1233 | return "Invalid chassis power command" | 
|  | 1234 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1235 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1236 | def chassisIdent(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1237 | """ | 
|  | 1238 | called by the chassis function. Controls the identify led of the chassis. Sets or gets the state | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1239 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1240 | @param host: string, the hostname or IP address of the bmc | 
|  | 1241 | @param args: contains additional arguments used by the fru sub command | 
|  | 1242 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1243 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1244 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1245 | if(args.identcmd == 'on'): | 
|  | 1246 | print("Attempting to turn identify light on...:") | 
|  | 1247 | url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1248 | data = '{"data":true}' | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1249 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1250 | res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1251 | except(requests.exceptions.Timeout): | 
|  | 1252 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1253 | return res.text | 
|  | 1254 | elif(args.identcmd == 'off'): | 
|  | 1255 | print("Attempting to turn identify light off...:") | 
|  | 1256 | url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1257 | data = '{"data":false}' | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1258 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1259 | res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1260 | except(requests.exceptions.Timeout): | 
|  | 1261 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1262 | return res.text | 
|  | 1263 | elif(args.identcmd == 'status'): | 
|  | 1264 | url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1265 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1266 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1267 | except(requests.exceptions.Timeout): | 
|  | 1268 | return(connectionErrHandler(args.json, "Timeout", None)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1269 | status = json.loads(res.text)['data'] | 
|  | 1270 | if(args.json): | 
|  | 1271 | return status | 
|  | 1272 | else: | 
|  | 1273 | if status['Asserted'] == 0: | 
|  | 1274 | return "Identify light is off" | 
|  | 1275 | else: | 
|  | 1276 | return "Identify light is blinking" | 
|  | 1277 | else: | 
|  | 1278 | return "Invalid chassis identify command" | 
|  | 1279 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1280 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1281 | def chassis(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1282 | """ | 
|  | 1283 | controls the different chassis commands | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1284 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1285 | @param host: string, the hostname or IP address of the bmc | 
|  | 1286 | @param args: contains additional arguments used by the fru sub command | 
|  | 1287 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1288 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1289 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1290 | if(hasattr(args, 'powcmd')): | 
|  | 1291 | result = chassisPower(host,args,session) | 
|  | 1292 | elif(hasattr(args, 'identcmd')): | 
|  | 1293 | result = chassisIdent(host, args, session) | 
|  | 1294 | else: | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 1295 | return "This feature is not yet implemented" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1296 | return result | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1297 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1298 | def bmcDumpRetrieve(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1299 | """ | 
|  | 1300 | Downloads a dump file from the bmc | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1301 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1302 | @param host: string, the hostname or IP address of the bmc | 
|  | 1303 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1304 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1305 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1306 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1307 | dumpNum = args.dumpNum | 
|  | 1308 | if (args.dumpSaveLoc is not None): | 
|  | 1309 | saveLoc = args.dumpSaveLoc | 
|  | 1310 | else: | 
| Justin Thaler | cf1deae | 2018-05-25 19:35:21 -0500 | [diff] [blame] | 1311 | saveLoc = tempfile.gettempdir() | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1312 | url ='https://'+host+'/download/dump/' + str(dumpNum) | 
|  | 1313 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1314 | r = session.get(url, headers=jsonHeader, stream=True, verify=False, timeout=baseTimeout) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1315 | if (args.dumpSaveLoc is not None): | 
|  | 1316 | if os.path.exists(saveLoc): | 
|  | 1317 | if saveLoc[-1] != os.path.sep: | 
|  | 1318 | saveLoc = saveLoc + os.path.sep | 
|  | 1319 | filename = saveLoc + host+'-dump' + str(dumpNum) + '.tar.xz' | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1320 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1321 | else: | 
|  | 1322 | return 'Invalid save location specified' | 
|  | 1323 | else: | 
| Justin Thaler | cf1deae | 2018-05-25 19:35:21 -0500 | [diff] [blame] | 1324 | filename = tempfile.gettempdir()+os.sep + host+'-dump' + str(dumpNum) + '.tar.xz' | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1325 |  | 
|  | 1326 | with open(filename, 'wb') as f: | 
|  | 1327 | for chunk in r.iter_content(chunk_size =1024): | 
|  | 1328 | if chunk: | 
|  | 1329 | f.write(chunk) | 
|  | 1330 | return 'Saved as ' + filename | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1331 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1332 | except(requests.exceptions.Timeout): | 
|  | 1333 | return connectionErrHandler(args.json, "Timeout", None) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1334 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1335 | except(requests.exceptions.ConnectionError) as err: | 
|  | 1336 | return connectionErrHandler(args.json, "ConnectionError", err) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1337 |  | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1338 | def bmcDumpList(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1339 | """ | 
|  | 1340 | Lists the number of dump files on the bmc | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1341 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1342 | @param host: string, the hostname or IP address of the bmc | 
|  | 1343 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1344 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1345 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1346 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1347 | url ='https://'+host+'/xyz/openbmc_project/dump/list' | 
|  | 1348 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1349 | r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | 3a5771b | 2019-01-23 14:31:52 -0600 | [diff] [blame] | 1350 | dumpList = r.json() | 
|  | 1351 | return dumpList | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1352 | except(requests.exceptions.Timeout): | 
|  | 1353 | return connectionErrHandler(args.json, "Timeout", None) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1354 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1355 | except(requests.exceptions.ConnectionError) as err: | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1356 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 1357 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1358 | def bmcDumpDelete(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1359 | """ | 
|  | 1360 | Deletes BMC dump files from the bmc | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1361 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1362 | @param host: string, the hostname or IP address of the bmc | 
|  | 1363 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1364 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1365 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1366 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1367 | dumpList = [] | 
|  | 1368 | successList = [] | 
|  | 1369 | failedList = [] | 
|  | 1370 | if args.dumpNum is not None: | 
|  | 1371 | if isinstance(args.dumpNum, list): | 
|  | 1372 | dumpList = args.dumpNum | 
|  | 1373 | else: | 
|  | 1374 | dumpList.append(args.dumpNum) | 
|  | 1375 | for dumpNum in dumpList: | 
|  | 1376 | url ='https://'+host+'/xyz/openbmc_project/dump/entry/'+str(dumpNum)+'/action/Delete' | 
|  | 1377 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1378 | r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1379 | if r.status_code == 200: | 
|  | 1380 | successList.append(str(dumpNum)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1381 | else: | 
|  | 1382 | failedList.append(str(dumpNum)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1383 | except(requests.exceptions.Timeout): | 
|  | 1384 | return connectionErrHandler(args.json, "Timeout", None) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1385 | except(requests.exceptions.ConnectionError) as err: | 
|  | 1386 | return connectionErrHandler(args.json, "ConnectionError", err) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1387 | output = "Successfully deleted dumps: " + ', '.join(successList) | 
|  | 1388 | if(len(failedList)>0): | 
|  | 1389 | output+= '\nFailed to delete dumps: ' + ', '.join(failedList) | 
|  | 1390 | return output | 
|  | 1391 | else: | 
|  | 1392 | return 'You must specify an entry number to delete' | 
|  | 1393 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1394 | def bmcDumpDeleteAll(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1395 | """ | 
|  | 1396 | Deletes All BMC dump files from the bmc | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1397 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1398 | @param host: string, the hostname or IP address of the bmc | 
|  | 1399 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1400 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1401 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1402 | """ | 
|  | 1403 | dumpResp = bmcDumpList(host, args, session) | 
|  | 1404 | if 'FQPSPIN0000M' in dumpResp or 'FQPSPIN0001M'in dumpResp: | 
|  | 1405 | return dumpResp | 
| Justin Thaler | 3a5771b | 2019-01-23 14:31:52 -0600 | [diff] [blame] | 1406 | dumpList = dumpResp['data'] | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1407 | d = vars(args) | 
|  | 1408 | dumpNums = [] | 
|  | 1409 | for dump in dumpList: | 
|  | 1410 | if '/xyz/openbmc_project/dump/internal/manager' not in dump: | 
|  | 1411 | dumpNums.append(int(dump.strip().split('/')[-1])) | 
|  | 1412 | d['dumpNum'] = dumpNums | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1413 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1414 | return bmcDumpDelete(host, args, session) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1415 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1416 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1417 | def bmcDumpCreate(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1418 | """ | 
|  | 1419 | Creates a bmc dump file | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1420 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1421 | @param host: string, the hostname or IP address of the bmc | 
|  | 1422 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1423 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1424 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1425 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1426 | url = 'https://'+host+'/xyz/openbmc_project/dump/action/CreateDump' | 
|  | 1427 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1428 | r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout) | 
| Matt Spinler | eae05b0 | 2019-01-24 12:59:34 -0600 | [diff] [blame] | 1429 | if(r.status_code == 200 and not args.json): | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1430 | return ('Dump successfully created') | 
| Justin Thaler | 3a5771b | 2019-01-23 14:31:52 -0600 | [diff] [blame] | 1431 | elif(args.json): | 
|  | 1432 | return r.json() | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1433 | else: | 
|  | 1434 | return ('Failed to create dump') | 
|  | 1435 | except(requests.exceptions.Timeout): | 
|  | 1436 | return connectionErrHandler(args.json, "Timeout", None) | 
|  | 1437 | except(requests.exceptions.ConnectionError) as err: | 
|  | 1438 | return connectionErrHandler(args.json, "ConnectionError", err) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1439 |  | 
|  | 1440 |  | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1441 | def csdDumpInitiate(host, args, session): | 
|  | 1442 | """ | 
|  | 1443 | Starts the process of getting the current list of dumps then initiates the creation of one. | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1444 |  | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1445 | @param host: string, the hostname or IP address of the bmc | 
|  | 1446 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1447 | @param session: the active session to use | 
|  | 1448 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1449 | """ | 
|  | 1450 | errorInfo = "" | 
|  | 1451 | dumpcount = 0 | 
|  | 1452 | try: | 
|  | 1453 | d = vars(args) | 
|  | 1454 | d['json'] = True | 
|  | 1455 | except Exception as e: | 
|  | 1456 | errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e) | 
|  | 1457 |  | 
|  | 1458 | try: | 
|  | 1459 | for i in range(3): | 
|  | 1460 | dumpInfo = bmcDumpList(host, args, session) | 
|  | 1461 | if 'data' in dumpInfo: | 
|  | 1462 | dumpcount = len(dumpInfo['data']) | 
|  | 1463 | break | 
|  | 1464 | else: | 
|  | 1465 | errorInfo+= "Dump List Message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n" | 
|  | 1466 | except Exception as e: | 
|  | 1467 | errorInfo+= "Failed to collect the list of dumps.\nException: {eInfo}\n".format(eInfo=e) | 
|  | 1468 |  | 
|  | 1469 | #Create a user initiated dump | 
|  | 1470 | try: | 
|  | 1471 | for i in range(3): | 
|  | 1472 | dumpcreated = bmcDumpCreate(host, args, session) | 
|  | 1473 | if 'message' in dumpcreated: | 
|  | 1474 | if 'ok' in dumpcreated['message'].lower(): | 
|  | 1475 | break | 
|  | 1476 | else: | 
|  | 1477 | errorInfo+= "Dump create message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n" | 
|  | 1478 | else: | 
|  | 1479 | errorInfo+= "Dump create message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n" | 
|  | 1480 | except Exception as e: | 
|  | 1481 | errorInfo+= "Dump create exception encountered: {eInfo}\n".format(eInfo=e) | 
|  | 1482 |  | 
|  | 1483 | output = {} | 
|  | 1484 | output['errors'] = errorInfo | 
|  | 1485 | output['dumpcount'] = dumpcount | 
|  | 1486 | return output | 
|  | 1487 |  | 
|  | 1488 | def csdInventory(host, args,session, fileDir): | 
|  | 1489 | """ | 
|  | 1490 | Collects the BMC inventory, retrying if necessary | 
|  | 1491 |  | 
|  | 1492 | @param host: string, the hostname or IP address of the bmc | 
|  | 1493 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1494 | @param session: the active session to use | 
|  | 1495 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1496 | @param fileDir: string representation of the path to use for putting files created | 
|  | 1497 | """ | 
|  | 1498 | errorInfo = "===========Inventory =============\n" | 
|  | 1499 | output={} | 
|  | 1500 | inventoryCollected = False | 
|  | 1501 | try: | 
|  | 1502 | for i in range(3): | 
|  | 1503 | frulist = fruPrint(host, args, session) | 
|  | 1504 | if 'Hardware' in frulist: | 
|  | 1505 | inventoryCollected = True | 
|  | 1506 | break | 
|  | 1507 | else: | 
|  | 1508 | errorInfo += json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n' | 
|  | 1509 | except Exception as e: | 
|  | 1510 | errorInfo += "Inventory collection exception: {eInfo}\n".format(eInfo=e) | 
|  | 1511 | if inventoryCollected: | 
|  | 1512 | try: | 
|  | 1513 | with open(fileDir +os.sep+'inventory.txt', 'w') as f: | 
|  | 1514 | f.write(json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n') | 
|  | 1515 | print("Inventory collected and stored in " + fileDir + os.sep + "inventory.txt") | 
|  | 1516 | output['fileLoc'] = fileDir+os.sep+'inventory.txt' | 
|  | 1517 | except Exception as e: | 
|  | 1518 | print("Failed to write inventory to file.") | 
|  | 1519 | errorInfo += "Error writing inventory to the file. Exception: {eInfo}\n".format(eInfo=e) | 
|  | 1520 |  | 
|  | 1521 | output['errors'] = errorInfo | 
|  | 1522 |  | 
|  | 1523 | return output | 
|  | 1524 |  | 
|  | 1525 | def csdSensors(host, args,session, fileDir): | 
|  | 1526 | """ | 
|  | 1527 | Collects the BMC sensor readings, retrying if necessary | 
|  | 1528 |  | 
|  | 1529 | @param host: string, the hostname or IP address of the bmc | 
|  | 1530 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1531 | @param session: the active session to use | 
|  | 1532 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1533 | @param fileDir: string representation of the path to use for putting files created | 
|  | 1534 | """ | 
|  | 1535 | errorInfo = "===========Sensors =============\n" | 
|  | 1536 | sensorsCollected = False | 
|  | 1537 | output={} | 
|  | 1538 | try: | 
|  | 1539 | d = vars(args) | 
|  | 1540 | d['json'] = False | 
|  | 1541 | except Exception as e: | 
|  | 1542 | errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e) | 
|  | 1543 |  | 
|  | 1544 | try: | 
|  | 1545 | for i in range(3): | 
|  | 1546 | sensorReadings = sensor(host, args, session) | 
|  | 1547 | if 'OCC0' in sensorReadings: | 
|  | 1548 | sensorsCollected = True | 
|  | 1549 | break | 
|  | 1550 | else: | 
|  | 1551 | errorInfo += sensorReadings | 
|  | 1552 | except Exception as e: | 
|  | 1553 | errorInfo += "Sensor reading collection exception: {eInfo}\n".format(eInfo=e) | 
|  | 1554 | if sensorsCollected: | 
|  | 1555 | try: | 
|  | 1556 | with open(fileDir +os.sep+'sensorReadings.txt', 'w') as f: | 
|  | 1557 | f.write(sensorReadings) | 
|  | 1558 | print("Sensor readings collected and stored in " + fileDir + os.sep+ "sensorReadings.txt") | 
|  | 1559 | output['fileLoc'] = fileDir+os.sep+'sensorReadings.txt' | 
|  | 1560 | except Exception as e: | 
|  | 1561 | print("Failed to write sensor readings to file system.") | 
|  | 1562 | errorInfo += "Error writing sensor readings to the file. Exception: {eInfo}\n".format(eInfo=e) | 
|  | 1563 |  | 
|  | 1564 | output['errors'] = errorInfo | 
|  | 1565 | return output | 
|  | 1566 |  | 
|  | 1567 | def csdLEDs(host,args, session, fileDir): | 
|  | 1568 | """ | 
|  | 1569 | Collects the BMC LED status, retrying if necessary | 
|  | 1570 |  | 
|  | 1571 | @param host: string, the hostname or IP address of the bmc | 
|  | 1572 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1573 | @param session: the active session to use | 
|  | 1574 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1575 | @param fileDir: string representation of the path to use for putting files created | 
|  | 1576 | """ | 
|  | 1577 | errorInfo = "===========LEDs =============\n" | 
|  | 1578 | ledsCollected = False | 
|  | 1579 | output={} | 
|  | 1580 | try: | 
|  | 1581 | d = vars(args) | 
|  | 1582 | d['json'] = True | 
|  | 1583 | except Exception as e: | 
|  | 1584 | errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e) | 
|  | 1585 | try: | 
|  | 1586 | url="https://"+host+"/xyz/openbmc_project/led/enumerate" | 
|  | 1587 | httpHeader = {'Content-Type':'application/json'} | 
|  | 1588 | for i in range(3): | 
|  | 1589 | try: | 
|  | 1590 | ledRes = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
|  | 1591 | if ledRes.status_code == 200: | 
|  | 1592 | ledsCollected = True | 
|  | 1593 | leds = ledRes.json()['data'] | 
|  | 1594 | break | 
|  | 1595 | else: | 
|  | 1596 | errorInfo += ledRes.text | 
|  | 1597 | except(requests.exceptions.Timeout): | 
|  | 1598 | errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n' | 
|  | 1599 | except(requests.exceptions.ConnectionError) as err: | 
|  | 1600 | errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n' | 
|  | 1601 | except Exception as e: | 
|  | 1602 | errorInfo += "LED status collection exception: {eInfo}\n".format(eInfo=e) | 
|  | 1603 |  | 
|  | 1604 | if ledsCollected: | 
|  | 1605 | try: | 
|  | 1606 | with open(fileDir +os.sep+'ledStatus.txt', 'w') as f: | 
|  | 1607 | f.write(json.dumps(leds, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n') | 
|  | 1608 | print("LED status collected and stored in " + fileDir + os.sep+ "ledStatus.txt") | 
|  | 1609 | output['fileLoc'] = fileDir+os.sep+'ledStatus.txt' | 
|  | 1610 | except Exception as e: | 
|  | 1611 | print("Failed to write LED status to file system.") | 
|  | 1612 | errorInfo += "Error writing LED status to the file. Exception: {eInfo}\n".format(eInfo=e) | 
|  | 1613 |  | 
|  | 1614 | output['errors'] = errorInfo | 
|  | 1615 | return output | 
|  | 1616 |  | 
|  | 1617 | def csdSelShortList(host, args, session, fileDir): | 
|  | 1618 | """ | 
|  | 1619 | Collects the BMC log entries, retrying if necessary | 
|  | 1620 |  | 
|  | 1621 | @param host: string, the hostname or IP address of the bmc | 
|  | 1622 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1623 | @param session: the active session to use | 
|  | 1624 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1625 | @param fileDir: string representation of the path to use for putting files created | 
|  | 1626 | """ | 
|  | 1627 | errorInfo = "===========SEL Short List =============\n" | 
|  | 1628 | selsCollected = False | 
|  | 1629 | output={} | 
|  | 1630 | try: | 
|  | 1631 | d = vars(args) | 
|  | 1632 | d['json'] = False | 
|  | 1633 | except Exception as e: | 
|  | 1634 | errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e) | 
|  | 1635 |  | 
|  | 1636 | try: | 
|  | 1637 | for i in range(3): | 
|  | 1638 | sels = selPrint(host,args,session) | 
|  | 1639 | if '----Active Alerts----' in sels or 'No log entries found' in sels or '----Historical Alerts----' in sels: | 
|  | 1640 | selsCollected = True | 
|  | 1641 | break | 
|  | 1642 | else: | 
|  | 1643 | errorInfo += sels + '\n' | 
|  | 1644 | except Exception as e: | 
|  | 1645 | errorInfo += "SEL short list collection exception: {eInfo}\n".format(eInfo=e) | 
|  | 1646 |  | 
|  | 1647 | if selsCollected: | 
|  | 1648 | try: | 
|  | 1649 | with open(fileDir +os.sep+'SELshortlist.txt', 'w') as f: | 
|  | 1650 | f.write(sels) | 
|  | 1651 | print("SEL short list collected and stored in " + fileDir + os.sep+ "SELshortlist.txt") | 
|  | 1652 | output['fileLoc'] = fileDir+os.sep+'SELshortlist.txt' | 
|  | 1653 | except Exception as e: | 
|  | 1654 | print("Failed to write SEL short list to file system.") | 
|  | 1655 | errorInfo += "Error writing SEL short list to the file. Exception: {eInfo}\n".format(eInfo=e) | 
|  | 1656 |  | 
|  | 1657 | output['errors'] = errorInfo | 
|  | 1658 | return output | 
|  | 1659 |  | 
|  | 1660 | def csdParsedSels(host, args, session, fileDir): | 
|  | 1661 | """ | 
|  | 1662 | Collects the BMC log entries, retrying if necessary | 
|  | 1663 |  | 
|  | 1664 | @param host: string, the hostname or IP address of the bmc | 
|  | 1665 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1666 | @param session: the active session to use | 
|  | 1667 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1668 | @param fileDir: string representation of the path to use for putting files created | 
|  | 1669 | """ | 
|  | 1670 | errorInfo = "===========SEL Parsed List =============\n" | 
|  | 1671 | selsCollected = False | 
|  | 1672 | output={} | 
|  | 1673 | try: | 
|  | 1674 | d = vars(args) | 
|  | 1675 | d['json'] = True | 
|  | 1676 | d['fullEsel'] = True | 
|  | 1677 | except Exception as e: | 
|  | 1678 | errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e) | 
|  | 1679 |  | 
|  | 1680 | try: | 
|  | 1681 | for i in range(3): | 
|  | 1682 | parsedfullsels = json.loads(selPrint(host,args,session)) | 
|  | 1683 | if 'numAlerts' in parsedfullsels: | 
|  | 1684 | selsCollected = True | 
|  | 1685 | break | 
|  | 1686 | else: | 
|  | 1687 | errorInfo += parsedfullsels + '\n' | 
|  | 1688 | except Exception as e: | 
|  | 1689 | errorInfo += "Parsed full SELs collection exception: {eInfo}\n".format(eInfo=e) | 
|  | 1690 |  | 
|  | 1691 | if selsCollected: | 
|  | 1692 | try: | 
|  | 1693 | sortedSELs = sortSELs(parsedfullsels) | 
|  | 1694 | with open(fileDir +os.sep+'parsedSELs.txt', 'w') as f: | 
|  | 1695 | for log in sortedSELs[0]: | 
|  | 1696 | esel = "" | 
|  | 1697 | parsedfullsels[sortedSELs[1][str(log)]]['timestamp'] = datetime.datetime.fromtimestamp(int(parsedfullsels[sortedSELs[1][str(log)]]['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S") | 
|  | 1698 | if ('raweSEL' in parsedfullsels[sortedSELs[1][str(log)]] and args.devdebug): | 
|  | 1699 | esel = parsedfullsels[sortedSELs[1][str(log)]]['raweSEL'] | 
|  | 1700 | del parsedfullsels[sortedSELs[1][str(log)]]['raweSEL'] | 
|  | 1701 | f.write(json.dumps(parsedfullsels[sortedSELs[1][str(log)]],sort_keys=True, indent=4, separators=(',', ': '))) | 
|  | 1702 | if(args.devdebug and esel != ""): | 
|  | 1703 | f.write(parseESEL(args, esel)) | 
|  | 1704 | print("Parsed SELs collected and stored in " + fileDir + os.sep+ "parsedSELs.txt") | 
|  | 1705 | output['fileLoc'] = fileDir+os.sep+'parsedSELs.txt' | 
|  | 1706 | except Exception as e: | 
|  | 1707 | print("Failed to write fully parsed SELs to file system.") | 
|  | 1708 | errorInfo += "Error writing fully parsed SELs to the file. Exception: {eInfo}\n".format(eInfo=e) | 
|  | 1709 |  | 
|  | 1710 | output['errors'] = errorInfo | 
|  | 1711 | return output | 
|  | 1712 |  | 
|  | 1713 | def csdFullEnumeration(host, args, session, fileDir): | 
|  | 1714 | """ | 
|  | 1715 | Collects a full enumeration of /xyz/openbmc_project/, retrying if necessary | 
|  | 1716 |  | 
|  | 1717 | @param host: string, the hostname or IP address of the bmc | 
|  | 1718 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1719 | @param session: the active session to use | 
|  | 1720 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1721 | @param fileDir: string representation of the path to use for putting files created | 
|  | 1722 | """ | 
|  | 1723 | errorInfo = "===========BMC Full Enumeration =============\n" | 
|  | 1724 | bmcFullCollected = False | 
|  | 1725 | output={} | 
|  | 1726 | try: | 
|  | 1727 | d = vars(args) | 
|  | 1728 | d['json'] = True | 
|  | 1729 | except Exception as e: | 
|  | 1730 | errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e) | 
|  | 1731 | try: | 
|  | 1732 | print("Attempting to get a full BMC enumeration") | 
|  | 1733 | url="https://"+host+"/xyz/openbmc_project/enumerate" | 
|  | 1734 | httpHeader = {'Content-Type':'application/json'} | 
|  | 1735 | for i in range(3): | 
|  | 1736 | try: | 
|  | 1737 | bmcRes = session.get(url, headers=jsonHeader, verify=False, timeout=180) | 
|  | 1738 | if bmcRes.status_code == 200: | 
|  | 1739 | bmcFullCollected = True | 
|  | 1740 | fullEnumeration = bmcRes.json() | 
|  | 1741 | break | 
|  | 1742 | else: | 
|  | 1743 | errorInfo += bmcRes.text | 
|  | 1744 | except(requests.exceptions.Timeout): | 
|  | 1745 | errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n' | 
|  | 1746 | except(requests.exceptions.ConnectionError) as err: | 
|  | 1747 | errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n' | 
|  | 1748 | except Exception as e: | 
|  | 1749 | errorInfo += "RAW BMC data collection exception: {eInfo}\n".format(eInfo=e) | 
|  | 1750 |  | 
|  | 1751 | if bmcFullCollected: | 
|  | 1752 | try: | 
|  | 1753 | with open(fileDir +os.sep+'bmcFullRaw.txt', 'w') as f: | 
|  | 1754 | f.write(json.dumps(fullEnumeration, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n') | 
|  | 1755 | print("RAW BMC data collected and saved into " + fileDir + os.sep+ "bmcFullRaw.txt") | 
|  | 1756 | output['fileLoc'] = fileDir+os.sep+'bmcFullRaw.txt' | 
|  | 1757 | except Exception as e: | 
|  | 1758 | print("Failed to write RAW BMC data  to file system.") | 
|  | 1759 | errorInfo += "Error writing RAW BMC data collection to the file. Exception: {eInfo}\n".format(eInfo=e) | 
|  | 1760 |  | 
|  | 1761 | output['errors'] = errorInfo | 
|  | 1762 | return output | 
|  | 1763 |  | 
|  | 1764 | def csdCollectAllDumps(host, args, session, fileDir): | 
|  | 1765 | """ | 
|  | 1766 | Collects all of the bmc dump files and stores them in fileDir | 
|  | 1767 |  | 
|  | 1768 | @param host: string, the hostname or IP address of the bmc | 
|  | 1769 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1770 | @param session: the active session to use | 
|  | 1771 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1772 | @param fileDir: string representation of the path to use for putting files created | 
|  | 1773 | """ | 
|  | 1774 |  | 
|  | 1775 | errorInfo = "===========BMC Dump Collection =============\n" | 
|  | 1776 | dumpListCollected = False | 
|  | 1777 | output={} | 
|  | 1778 | dumpList = {} | 
|  | 1779 | try: | 
|  | 1780 | d = vars(args) | 
|  | 1781 | d['json'] = True | 
|  | 1782 | d['dumpSaveLoc'] = fileDir | 
|  | 1783 | except Exception as e: | 
|  | 1784 | errorInfo += "Failed to set the json flag to True, or failed to set the dumpSave Location \n Exception: {eInfo}\n".format(eInfo=e) | 
|  | 1785 |  | 
|  | 1786 | print('Collecting bmc dump files') | 
|  | 1787 |  | 
|  | 1788 | try: | 
|  | 1789 | for i in range(3): | 
|  | 1790 | dumpResp = bmcDumpList(host, args, session) | 
|  | 1791 | if 'message' in dumpResp: | 
|  | 1792 | if 'ok' in dumpResp['message'].lower(): | 
|  | 1793 | dumpList = dumpResp['data'] | 
|  | 1794 | dumpListCollected = True | 
|  | 1795 | break | 
|  | 1796 | else: | 
|  | 1797 | errorInfo += "Status was not OK when retrieving the list of dumps available. \n Response: \n{resp}\n".format(resp=dumpResp) | 
|  | 1798 | else: | 
|  | 1799 | errorInfo += "Invalid response received from the BMC while retrieving the list of dumps available.\n {resp}\n".format(resp=dumpResp) | 
|  | 1800 | except Exception as e: | 
|  | 1801 | errorInfo += "BMC dump list exception: {eInfo}\n".format(eInfo=e) | 
|  | 1802 |  | 
|  | 1803 | if dumpListCollected: | 
|  | 1804 | output['fileList'] = [] | 
|  | 1805 | for dump in dumpList: | 
|  | 1806 | try: | 
|  | 1807 | if '/xyz/openbmc_project/dump/internal/manager' not in dump: | 
|  | 1808 | d['dumpNum'] = int(dump.strip().split('/')[-1]) | 
|  | 1809 | print('retrieving dump file ' + str(d['dumpNum'])) | 
|  | 1810 | filename = bmcDumpRetrieve(host, args, session).split('Saved as ')[-1] | 
|  | 1811 | output['fileList'].append(filename) | 
|  | 1812 | except Exception as e: | 
|  | 1813 | print("Unable to collect dump: {dumpInfo}".format(dumpInfo=dump)) | 
|  | 1814 | errorInfo += "Exception collecting a bmc dump {dumpInfo}\n {eInfo}\n".format(dumpInfo=dump, eInfo=e) | 
|  | 1815 | output['errors'] = errorInfo | 
|  | 1816 | return output | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1817 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1818 | def collectServiceData(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1819 | """ | 
|  | 1820 | Collects all data needed for service from the BMC | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1821 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1822 | @param host: string, the hostname or IP address of the bmc | 
|  | 1823 | @param args: contains additional arguments used by the collectServiceData sub command | 
|  | 1824 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1825 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1826 | """ | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1827 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 1828 | global toolVersion | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1829 | filelist = [] | 
|  | 1830 | errorInfo = "" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1831 |  | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1832 | #get current number of bmc dumps and create a new bmc dump | 
|  | 1833 | dumpInitdata = csdDumpInitiate(host, args, session) | 
|  | 1834 | dumpcount = dumpInitdata['dumpcount'] | 
|  | 1835 | errorInfo += dumpInitdata['errors'] | 
|  | 1836 | #create the directory to put files | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1837 | try: | 
|  | 1838 | args.silent = True | 
| Justin Thaler | cf1deae | 2018-05-25 19:35:21 -0500 | [diff] [blame] | 1839 | myDir = tempfile.gettempdir()+os.sep + host + "--" + datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%S") | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1840 | os.makedirs(myDir) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1841 |  | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1842 | except Exception as e: | 
|  | 1843 | print('Unable to create the temporary directory for data collection. Ensure sufficient privileges to create temporary directory. Aborting.') | 
|  | 1844 | return("Python exception: {eInfo}".format(eInfo = e)) | 
|  | 1845 |  | 
|  | 1846 | #Collect Inventory | 
|  | 1847 | inventoryData = csdInventory(host, args, session, myDir) | 
|  | 1848 | if 'fileLoc' in inventoryData: | 
|  | 1849 | filelist.append(inventoryData['fileLoc']) | 
|  | 1850 | errorInfo += inventoryData['errors'] | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1851 | #Read all the sensor and OCC status | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1852 | sensorData = csdSensors(host,args,session,myDir) | 
|  | 1853 | if 'fileLoc' in sensorData: | 
|  | 1854 | filelist.append(sensorData['fileLoc']) | 
|  | 1855 | errorInfo += sensorData['errors'] | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1856 | #Collect all of the LEDs status | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1857 | ledStatus = csdLEDs(host, args, session, myDir) | 
|  | 1858 | if 'fileLoc' in ledStatus: | 
|  | 1859 | filelist.append(ledStatus['fileLoc']) | 
|  | 1860 | errorInfo += ledStatus['errors'] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1861 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1862 | #Collect the bmc logs | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1863 | selShort = csdSelShortList(host, args, session, myDir) | 
|  | 1864 | if 'fileLoc' in selShort: | 
|  | 1865 | filelist.append(selShort['fileLoc']) | 
|  | 1866 | errorInfo += selShort['errors'] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1867 |  | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1868 | parsedSELs = csdParsedSels(host, args, session, myDir) | 
|  | 1869 | if 'fileLoc' in parsedSELs: | 
|  | 1870 | filelist.append(parsedSELs['fileLoc']) | 
|  | 1871 | errorInfo += parsedSELs['errors'] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1872 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1873 | #collect RAW bmc enumeration | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1874 | bmcRaw = csdFullEnumeration(host, args, session, myDir) | 
|  | 1875 | if 'fileLoc' in bmcRaw: | 
|  | 1876 | filelist.append(bmcRaw['fileLoc']) | 
|  | 1877 | errorInfo += bmcRaw['errors'] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1878 |  | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1879 | #wait for new dump to finish being created | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1880 | waitingForNewDump = True | 
|  | 1881 | count = 0; | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1882 | print("Waiting for new BMC dump to finish being created.") | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1883 | while(waitingForNewDump): | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1884 | dumpList = bmcDumpList(host, args, session)['data'] | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1885 | if len(dumpList) > dumpcount: | 
|  | 1886 | waitingForNewDump = False | 
|  | 1887 | break; | 
|  | 1888 | elif(count>30): | 
|  | 1889 | print("Timed out waiting for bmc to make a new dump file. Dump space may be full.") | 
|  | 1890 | break; | 
|  | 1891 | else: | 
|  | 1892 | time.sleep(2) | 
|  | 1893 | count += 1 | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1894 |  | 
|  | 1895 | #collect all of the dump files | 
|  | 1896 | getBMCDumps = csdCollectAllDumps(host, args, session, myDir) | 
|  | 1897 | if 'fileList' in getBMCDumps: | 
|  | 1898 | filelist+= getBMCDumps['fileList'] | 
|  | 1899 | errorInfo += getBMCDumps['errors'] | 
|  | 1900 |  | 
|  | 1901 | #write the runtime errors to a file | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1902 | try: | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1903 | with open(myDir +os.sep+'openbmctoolRuntimeErrors.txt', 'w') as f: | 
|  | 1904 | f.write(errorInfo) | 
|  | 1905 | print("OpenBMC tool runtime errors collected and stored in " + myDir + os.sep+ "openbmctoolRuntimeErrors.txt") | 
|  | 1906 | filelist.append(myDir+os.sep+'openbmctoolRuntimeErrors.txt') | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1907 | except Exception as e: | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1908 | print("Failed to write OpenBMC tool runtime errors to file system.") | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1909 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1910 | #create the zip file | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1911 | try: | 
| Justin Thaler | cf1deae | 2018-05-25 19:35:21 -0500 | [diff] [blame] | 1912 | filename = myDir.split(tempfile.gettempdir()+os.sep)[-1] + "_" + toolVersion + '_openbmc.zip' | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1913 | zf = zipfile.ZipFile(myDir+os.sep + filename, 'w') | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1914 | for myfile in filelist: | 
|  | 1915 | zf.write(myfile, os.path.basename(myfile)) | 
|  | 1916 | zf.close() | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1917 | print("Zip file with all collected data created and stored in: {fileInfo}".format(fileInfo=myDir+os.sep+filename)) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1918 | except Exception as e: | 
|  | 1919 | print("Failed to create zip file with collected information") | 
| Justin Thaler | 666cf34 | 2019-01-23 14:44:27 -0600 | [diff] [blame] | 1920 | return "data collection finished" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 1921 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1922 |  | 
|  | 1923 | def healthCheck(host, args, session): | 
|  | 1924 | """ | 
|  | 1925 | runs a health check on the platform | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1926 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1927 | @param host: string, the hostname or IP address of the bmc | 
|  | 1928 | @param args: contains additional arguments used by the bmc sub command | 
|  | 1929 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1930 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 1931 | """ | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1932 | #check fru status and get as json to easily work through | 
|  | 1933 | d = vars(args) | 
|  | 1934 | useJson = d['json'] | 
|  | 1935 | d['json'] = True | 
|  | 1936 | d['verbose']= False | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1937 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1938 | frus = json.loads(fruStatus(host, args, session)) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1939 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1940 | hwStatus= "OK" | 
|  | 1941 | performanceStatus = "OK" | 
|  | 1942 | for key in frus: | 
|  | 1943 | if frus[key]["Functional"] == "No" and frus[key]["Present"] == "Yes": | 
|  | 1944 | hwStatus= "Degraded" | 
| Justin Thaler | fb9c81c | 2018-07-16 11:14:37 -0500 | [diff] [blame] | 1945 | if("power_supply" in key or "powersupply" in key): | 
|  | 1946 | gpuCount =0 | 
|  | 1947 | for comp in frus: | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1948 | if "gv100card" in comp: | 
|  | 1949 | gpuCount +=1 | 
|  | 1950 | if gpuCount > 4: | 
|  | 1951 | hwStatus = "Critical" | 
|  | 1952 | performanceStatus="Degraded" | 
|  | 1953 | break; | 
|  | 1954 | elif("fan" in key): | 
|  | 1955 | hwStatus = "Degraded" | 
|  | 1956 | else: | 
|  | 1957 | performanceStatus = "Degraded" | 
|  | 1958 | if useJson: | 
|  | 1959 | output = {"Hardware Status": hwStatus, "Performance": performanceStatus} | 
|  | 1960 | output = json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) | 
|  | 1961 | else: | 
|  | 1962 | output = ("Hardware Status: " + hwStatus + | 
|  | 1963 | "\nPerformance: " +performanceStatus ) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 1964 |  | 
|  | 1965 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1966 | #SW407886: Clear the duplicate entries | 
|  | 1967 | #collect the dups | 
|  | 1968 | d['devdebug'] = False | 
|  | 1969 | sels = json.loads(selPrint(host, args, session)) | 
|  | 1970 | logNums2Clr = [] | 
|  | 1971 | oldestLogNum={"logNum": "bogus" ,"key" : ""} | 
|  | 1972 | count = 0 | 
|  | 1973 | if sels['numAlerts'] > 0: | 
|  | 1974 | for key in sels: | 
|  | 1975 | if "numAlerts" in key: | 
|  | 1976 | continue | 
|  | 1977 | try: | 
|  | 1978 | if "slave@00:00/00:00:00:06/sbefifo1-dev0/occ1-dev0" in sels[key]['Message']: | 
|  | 1979 | count += 1 | 
|  | 1980 | if count > 1: | 
|  | 1981 | #preserve first occurrence | 
|  | 1982 | if sels[key]['timestamp'] < sels[oldestLogNum['key']]['timestamp']: | 
|  | 1983 | oldestLogNum['key']=key | 
|  | 1984 | oldestLogNum['logNum'] = sels[key]['logNum'] | 
|  | 1985 | else: | 
|  | 1986 | oldestLogNum['key']=key | 
|  | 1987 | oldestLogNum['logNum'] = sels[key]['logNum'] | 
|  | 1988 | logNums2Clr.append(sels[key]['logNum']) | 
|  | 1989 | except KeyError: | 
|  | 1990 | continue | 
|  | 1991 | if(count >0): | 
|  | 1992 | logNums2Clr.remove(oldestLogNum['logNum']) | 
|  | 1993 | #delete the dups | 
|  | 1994 | if count >1: | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 1995 | data = "{\"data\": [] }" | 
|  | 1996 | for logNum in logNums2Clr: | 
|  | 1997 | url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete" | 
|  | 1998 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 1999 | session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2000 | except(requests.exceptions.Timeout): | 
|  | 2001 | deleteFailed = True | 
|  | 2002 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2003 | deleteFailed = True | 
|  | 2004 | #End of defect resolve code | 
|  | 2005 | d['json'] = useJson | 
|  | 2006 | return output | 
|  | 2007 |  | 
|  | 2008 |  | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2009 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 2010 | def bmc(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2011 | """ | 
|  | 2012 | handles various bmc level commands, currently bmc rebooting | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2013 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2014 | @param host: string, the hostname or IP address of the bmc | 
|  | 2015 | @param args: contains additional arguments used by the bmc sub command | 
|  | 2016 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2017 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 2018 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 2019 | if(args.type is not None): | 
|  | 2020 | return bmcReset(host, args, session) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2021 | if(args.info): | 
|  | 2022 | return "Not implemented at this time" | 
|  | 2023 |  | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2024 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2025 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 2026 | def bmcReset(host, args, session): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2027 | """ | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2028 | controls resetting the bmc. warm reset reboots the bmc, cold reset removes the configuration and reboots. | 
|  | 2029 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2030 | @param host: string, the hostname or IP address of the bmc | 
|  | 2031 | @param args: contains additional arguments used by the bmcReset sub command | 
|  | 2032 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2033 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
|  | 2034 | """ | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2035 | if checkFWactivation(host, args, session): | 
|  | 2036 | return ("BMC reset control disabled during firmware activation") | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 2037 | if(args.type == "warm"): | 
|  | 2038 | print("\nAttempting to reboot the BMC...:") | 
|  | 2039 | url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2040 | data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}' | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2041 | res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 2042 | return res.text | 
|  | 2043 | elif(args.type =="cold"): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2044 | print("\nAttempting to reboot the BMC...:") | 
|  | 2045 | url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2046 | data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}' | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2047 | res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2048 | return res.text | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 2049 | else: | 
|  | 2050 | return "invalid command" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2051 |  | 
|  | 2052 | def gardClear(host, args, session): | 
|  | 2053 | """ | 
|  | 2054 | clears the gard records from the bmc | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2055 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2056 | @param host: string, the hostname or IP address of the bmc | 
|  | 2057 | @param args: contains additional arguments used by the gardClear sub command | 
|  | 2058 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2059 | """ | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2060 | url="https://"+host+"/org/open_power/control/gard/action/Reset" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2061 | data = '{"data":[]}' | 
|  | 2062 | try: | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2063 |  | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2064 | res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2065 | if res.status_code == 404: | 
|  | 2066 | return "Command not supported by this firmware version" | 
|  | 2067 | else: | 
|  | 2068 | return res.text | 
|  | 2069 | except(requests.exceptions.Timeout): | 
|  | 2070 | return connectionErrHandler(args.json, "Timeout", None) | 
|  | 2071 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2072 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2073 |  | 
|  | 2074 | def activateFWImage(host, args, session): | 
|  | 2075 | """ | 
|  | 2076 | activates a firmware image on the bmc | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2077 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2078 | @param host: string, the hostname or IP address of the bmc | 
|  | 2079 | @param args: contains additional arguments used by the fwflash sub command | 
|  | 2080 | @param session: the active session to use | 
|  | 2081 | @param fwID: the unique ID of the fw image to activate | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2082 | """ | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2083 | fwID = args.imageID | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2084 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2085 | #determine the existing versions | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2086 | url="https://"+host+"/xyz/openbmc_project/software/enumerate" | 
|  | 2087 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2088 | resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2089 | except(requests.exceptions.Timeout): | 
|  | 2090 | return connectionErrHandler(args.json, "Timeout", None) | 
|  | 2091 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2092 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2093 | existingSoftware = json.loads(resp.text)['data'] | 
|  | 2094 | altVersionID = '' | 
|  | 2095 | versionType = '' | 
|  | 2096 | imageKey = '/xyz/openbmc_project/software/'+fwID | 
|  | 2097 | if imageKey in existingSoftware: | 
|  | 2098 | versionType = existingSoftware[imageKey]['Purpose'] | 
|  | 2099 | for key in existingSoftware: | 
|  | 2100 | if imageKey == key: | 
|  | 2101 | continue | 
|  | 2102 | if 'Purpose' in existingSoftware[key]: | 
|  | 2103 | if versionType == existingSoftware[key]['Purpose']: | 
|  | 2104 | altVersionID = key.split('/')[-1] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2105 |  | 
|  | 2106 |  | 
|  | 2107 |  | 
|  | 2108 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2109 | url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/attr/Priority" | 
|  | 2110 | url1="https://"+host+"/xyz/openbmc_project/software/"+ altVersionID + "/attr/Priority" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2111 | data = "{\"data\": 0}" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2112 | data1 = "{\"data\": 1 }" | 
|  | 2113 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2114 | resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
|  | 2115 | resp1 = session.put(url1, headers=jsonHeader, data=data1, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2116 | except(requests.exceptions.Timeout): | 
|  | 2117 | return connectionErrHandler(args.json, "Timeout", None) | 
|  | 2118 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2119 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2120 | if(not args.json): | 
|  | 2121 | if resp.status_code == 200 and resp1.status_code == 200: | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2122 | return 'Firmware flash and activation completed. Please reboot the bmc and then boot the host OS for the changes to take effect. ' | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2123 | else: | 
|  | 2124 | return "Firmware activation failed." | 
|  | 2125 | else: | 
|  | 2126 | return resp.text + resp1.text | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2127 |  | 
|  | 2128 | def activateStatus(host, args, session): | 
|  | 2129 | if checkFWactivation(host, args, session): | 
|  | 2130 | return("Firmware is currently being activated. Do not reboot the BMC or start the Host OS") | 
|  | 2131 | else: | 
|  | 2132 | return("No firmware activations are pending") | 
|  | 2133 |  | 
|  | 2134 | def extractFWimage(path, imageType): | 
|  | 2135 | """ | 
|  | 2136 | extracts the bmc image and returns information about the package | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2137 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2138 | @param path: the path and file name of the firmware image | 
|  | 2139 | @param imageType: The type of image the user is trying to flash. Host or BMC | 
|  | 2140 | @return: the image id associated with the package. returns an empty string on error. | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2141 | """ | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2142 | f = tempfile.TemporaryFile() | 
|  | 2143 | tmpDir = tempfile.gettempdir() | 
|  | 2144 | newImageID = "" | 
|  | 2145 | if os.path.exists(path): | 
|  | 2146 | try: | 
|  | 2147 | imageFile = tarfile.open(path,'r') | 
|  | 2148 | contents = imageFile.getmembers() | 
|  | 2149 | for tf in contents: | 
|  | 2150 | if 'MANIFEST' in tf.name: | 
|  | 2151 | imageFile.extract(tf.name, path=tmpDir) | 
|  | 2152 | with open(tempfile.gettempdir() +os.sep+ tf.name, 'r') as imageInfo: | 
|  | 2153 | for line in imageInfo: | 
|  | 2154 | if 'purpose' in line: | 
|  | 2155 | purpose = line.split('=')[1] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2156 | if imageType not in purpose.split('.')[-1]: | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2157 | print('The specified image is not for ' + imageType) | 
|  | 2158 | print('Please try again with the image for ' + imageType) | 
|  | 2159 | return "" | 
|  | 2160 | if 'version' == line.split('=')[0]: | 
|  | 2161 | version = line.split('=')[1].strip().encode('utf-8') | 
|  | 2162 | m = hashlib.sha512() | 
|  | 2163 | m.update(version) | 
|  | 2164 | newImageID = m.hexdigest()[:8] | 
|  | 2165 | break | 
|  | 2166 | try: | 
|  | 2167 | os.remove(tempfile.gettempdir() +os.sep+ tf.name) | 
|  | 2168 | except OSError: | 
|  | 2169 | pass | 
|  | 2170 | return newImageID | 
|  | 2171 | except tarfile.ExtractError as e: | 
|  | 2172 | print('Unable to extract information from the firmware file.') | 
|  | 2173 | print('Ensure you have write access to the directory: ' + tmpDir) | 
|  | 2174 | return newImageID | 
|  | 2175 | except tarfile.TarError as e: | 
|  | 2176 | print('This is not a valid firmware file.') | 
|  | 2177 | return newImageID | 
|  | 2178 | print("This is not a valid firmware file.") | 
|  | 2179 | return newImageID | 
|  | 2180 | else: | 
|  | 2181 | print('The filename and path provided are not valid.') | 
|  | 2182 | return newImageID | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2183 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2184 | def getAllFWImageIDs(fwInvDict): | 
|  | 2185 | """ | 
|  | 2186 | gets a list of all the firmware image IDs | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2187 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2188 | @param fwInvDict: the dictionary to search for FW image IDs | 
|  | 2189 | @return: list containing string representation of the found image ids | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2190 | """ | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2191 | idList = [] | 
|  | 2192 | for key in fwInvDict: | 
|  | 2193 | if 'Version' in fwInvDict[key]: | 
|  | 2194 | idList.append(key.split('/')[-1]) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2195 | return idList | 
|  | 2196 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2197 | def fwFlash(host, args, session): | 
|  | 2198 | """ | 
|  | 2199 | updates the bmc firmware and pnor firmware | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2200 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2201 | @param host: string, the hostname or IP address of the bmc | 
|  | 2202 | @param args: contains additional arguments used by the fwflash sub command | 
|  | 2203 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2204 | """ | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2205 | d = vars(args) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2206 | if(args.type == 'bmc'): | 
|  | 2207 | purp = 'BMC' | 
|  | 2208 | else: | 
|  | 2209 | purp = 'Host' | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2210 |  | 
|  | 2211 | #check power state of the machine. No concurrent FW updates allowed | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2212 | d['powcmd'] = 'status' | 
|  | 2213 | powerstate = chassisPower(host, args, session) | 
|  | 2214 | if 'Chassis Power State: On' in powerstate: | 
|  | 2215 | return("Aborting firmware update. Host is powered on. Please turn off the host and try again.") | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2216 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2217 | #determine the existing images on the bmc | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2218 | url="https://"+host+"/xyz/openbmc_project/software/enumerate" | 
|  | 2219 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2220 | resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2221 | except(requests.exceptions.Timeout): | 
|  | 2222 | return connectionErrHandler(args.json, "Timeout", None) | 
|  | 2223 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2224 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2225 | oldsoftware = json.loads(resp.text)['data'] | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2226 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2227 | #Extract the tar and get information from the manifest file | 
|  | 2228 | newversionID = extractFWimage(args.fileloc, purp) | 
|  | 2229 | if  newversionID == "": | 
|  | 2230 | return "Unable to verify FW image." | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2231 |  | 
|  | 2232 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2233 | #check if the new image is already on the bmc | 
|  | 2234 | if newversionID not in getAllFWImageIDs(oldsoftware): | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2235 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2236 | #upload the file | 
|  | 2237 | httpHeader = {'Content-Type':'application/octet-stream'} | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 2238 | httpHeader.update(xAuthHeader) | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2239 | url="https://"+host+"/upload/image" | 
|  | 2240 | data=open(args.fileloc,'rb').read() | 
|  | 2241 | print("Uploading file to BMC") | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2242 | try: | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2243 | resp = session.post(url, headers=httpHeader, data=data, verify=False) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2244 | except(requests.exceptions.Timeout): | 
|  | 2245 | return connectionErrHandler(args.json, "Timeout", None) | 
|  | 2246 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2247 | return connectionErrHandler(args.json, "ConnectionError", err) | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2248 | if resp.status_code != 200: | 
|  | 2249 | return "Failed to upload the file to the bmc" | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2250 | else: | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2251 | print("Upload complete.") | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2252 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2253 | #verify bmc processed the image | 
|  | 2254 | software ={} | 
|  | 2255 | for i in range(0, 5): | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2256 | url="https://"+host+"/xyz/openbmc_project/software/enumerate" | 
|  | 2257 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2258 | resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2259 | except(requests.exceptions.Timeout): | 
|  | 2260 | return connectionErrHandler(args.json, "Timeout", None) | 
|  | 2261 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2262 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2263 | software = json.loads(resp.text)['data'] | 
|  | 2264 | #check if bmc is done processing the new image | 
|  | 2265 | if (newversionID in getAllFWImageIDs(software)): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2266 | break | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2267 | else: | 
|  | 2268 | time.sleep(15) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2269 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2270 | #activate the new image | 
|  | 2271 | print("Activating new image: "+newversionID) | 
|  | 2272 | url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID + "/attr/RequestedActivation" | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2273 | data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}' | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2274 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2275 | resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2276 | except(requests.exceptions.Timeout): | 
|  | 2277 | return connectionErrHandler(args.json, "Timeout", None) | 
|  | 2278 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2279 | return connectionErrHandler(args.json, "ConnectionError", err) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2280 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2281 | #wait for the activation to complete, timeout after ~1 hour | 
|  | 2282 | i=0 | 
|  | 2283 | while i < 360: | 
|  | 2284 | url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2285 | data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}' | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2286 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2287 | resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2288 | except(requests.exceptions.Timeout): | 
|  | 2289 | return connectionErrHandler(args.json, "Timeout", None) | 
|  | 2290 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2291 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2292 | fwInfo = json.loads(resp.text)['data'] | 
|  | 2293 | if 'Activating' not in fwInfo['Activation'] and 'Activating' not in fwInfo['RequestedActivation']: | 
|  | 2294 | print('') | 
|  | 2295 | break | 
|  | 2296 | else: | 
|  | 2297 | sys.stdout.write('.') | 
|  | 2298 | sys.stdout.flush() | 
|  | 2299 | time.sleep(10) #check every 10 seconds | 
|  | 2300 | return "Firmware flash and activation completed. Please reboot the bmc and then boot the host OS for the changes to take effect. " | 
|  | 2301 | else: | 
|  | 2302 | print("This image has been found on the bmc. Activating image: " + newversionID) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2303 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 2304 | d['imageID'] = newversionID | 
|  | 2305 | return activateFWImage(host, args, session) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 2306 |  | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2307 | def getFWInventoryAttributes(rawFWInvItem, ID): | 
|  | 2308 | """ | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2309 | gets and lists all of the firmware in the system. | 
|  | 2310 |  | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2311 | @return: returns a dictionary containing the image attributes | 
|  | 2312 | """ | 
|  | 2313 | reqActivation = rawFWInvItem["RequestedActivation"].split('.')[-1] | 
|  | 2314 | pendingActivation = "" | 
|  | 2315 | if reqActivation == "None": | 
|  | 2316 | pendingActivation = "No" | 
|  | 2317 | else: | 
|  | 2318 | pendingActivation = "Yes" | 
|  | 2319 | firmwareAttr = {ID: { | 
|  | 2320 | "Purpose": rawFWInvItem["Purpose"].split('.')[-1], | 
|  | 2321 | "Version": rawFWInvItem["Version"], | 
|  | 2322 | "RequestedActivation": pendingActivation, | 
|  | 2323 | "ID": ID}} | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2324 |  | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2325 | if "ExtendedVersion" in rawFWInvItem: | 
|  | 2326 | firmwareAttr[ID]['ExtendedVersion'] = rawFWInvItem['ExtendedVersion'].split(',') | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2327 | else: | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2328 | firmwareAttr[ID]['ExtendedVersion'] = "" | 
|  | 2329 | return firmwareAttr | 
|  | 2330 |  | 
|  | 2331 | def parseFWdata(firmwareDict): | 
|  | 2332 | """ | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2333 | creates a dictionary with parsed firmware data | 
|  | 2334 |  | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2335 | @return: returns a dictionary containing the image attributes | 
|  | 2336 | """ | 
|  | 2337 | firmwareInfoDict = {"Functional": {}, "Activated":{}, "NeedsActivated":{}} | 
|  | 2338 | for key in firmwareDict['data']: | 
|  | 2339 | #check for valid endpoint | 
|  | 2340 | if "Purpose" in firmwareDict['data'][key]: | 
|  | 2341 | id = key.split('/')[-1] | 
|  | 2342 | if firmwareDict['data'][key]['Activation'].split('.')[-1] == "Active": | 
|  | 2343 | fwActivated = True | 
|  | 2344 | else: | 
|  | 2345 | fwActivated = False | 
| Justin Thaler | cb68e06 | 2019-03-26 19:04:52 -0500 | [diff] [blame] | 2346 | if 'Priority' in firmwareDict['data'][key]: | 
|  | 2347 | if firmwareDict['data'][key]['Priority'] == 0: | 
|  | 2348 | firmwareInfoDict['Functional'].update(getFWInventoryAttributes(firmwareDict['data'][key], id)) | 
|  | 2349 | elif firmwareDict['data'][key]['Priority'] >= 0 and fwActivated: | 
|  | 2350 | firmwareInfoDict['Activated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id)) | 
|  | 2351 | else: | 
|  | 2352 | firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id)) | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2353 | else: | 
| Justin Thaler | cb68e06 | 2019-03-26 19:04:52 -0500 | [diff] [blame] | 2354 | firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id)) | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2355 | emptySections = [] | 
|  | 2356 | for key in firmwareInfoDict: | 
|  | 2357 | if len(firmwareInfoDict[key])<=0: | 
|  | 2358 | emptySections.append(key) | 
|  | 2359 | for key in emptySections: | 
|  | 2360 | del firmwareInfoDict[key] | 
|  | 2361 | return firmwareInfoDict | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2362 |  | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2363 | def displayFWInvenory(firmwareInfoDict, args): | 
|  | 2364 | """ | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2365 | gets and lists all of the firmware in the system. | 
|  | 2366 |  | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2367 | @return: returns a string containing all of the firmware information | 
|  | 2368 | """ | 
|  | 2369 | output = "" | 
|  | 2370 | if not args.json: | 
|  | 2371 | for key in firmwareInfoDict: | 
|  | 2372 | for subkey in firmwareInfoDict[key]: | 
|  | 2373 | firmwareInfoDict[key][subkey]['ExtendedVersion'] = str(firmwareInfoDict[key][subkey]['ExtendedVersion']) | 
|  | 2374 | if not args.verbose: | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2375 | output = "---Running Images---\n" | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2376 | colNames = ["Purpose", "Version", "ID"] | 
|  | 2377 | keylist = ["Purpose", "Version", "ID"] | 
|  | 2378 | output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"]) | 
|  | 2379 | if "Activated" in firmwareInfoDict: | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2380 | output += "\n---Available Images---\n" | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2381 | output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"]) | 
|  | 2382 | if "NeedsActivated" in firmwareInfoDict: | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2383 | output += "\n---Needs Activated Images---\n" | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2384 | output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"]) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2385 |  | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2386 | else: | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2387 | output = "---Running Images---\n" | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2388 | colNames = ["Purpose", "Version", "ID", "Pending Activation", "Extended Version"] | 
|  | 2389 | keylist = ["Purpose", "Version", "ID", "RequestedActivation", "ExtendedVersion"] | 
|  | 2390 | output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"]) | 
|  | 2391 | if "Activated" in firmwareInfoDict: | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2392 | output += "\n---Available Images---\n" | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2393 | output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"]) | 
|  | 2394 | if "NeedsActivated" in firmwareInfoDict: | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2395 | output += "\n---Needs Activated Images---\n" | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2396 | output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"]) | 
|  | 2397 | return output | 
|  | 2398 | else: | 
|  | 2399 | return str(json.dumps(firmwareInfoDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)) | 
|  | 2400 |  | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2401 | def firmwareList(host, args, session): | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2402 | """ | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2403 | gets and lists all of the firmware in the system. | 
|  | 2404 |  | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2405 | @return: returns a string containing all of the firmware information | 
|  | 2406 | """ | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2407 | url="https://{hostname}/xyz/openbmc_project/software/enumerate".format(hostname=host) | 
|  | 2408 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2409 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2410 | except(requests.exceptions.Timeout): | 
|  | 2411 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2412 | firmwareDict = json.loads(res.text) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2413 |  | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2414 | #sort the received information | 
|  | 2415 | firmwareInfoDict = parseFWdata(firmwareDict) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2416 |  | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 2417 | #display the information | 
|  | 2418 | return displayFWInvenory(firmwareInfoDict, args) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2419 |  | 
|  | 2420 |  | 
| Adriana Kobylak | 5af2fad | 2018-11-08 12:33:43 -0600 | [diff] [blame] | 2421 | def deleteFWVersion(host, args, session): | 
|  | 2422 | """ | 
|  | 2423 | deletes a firmware version on the BMC | 
|  | 2424 |  | 
|  | 2425 | @param host: string, the hostname or IP address of the BMC | 
|  | 2426 | @param args: contains additional arguments used by the fwflash sub command | 
|  | 2427 | @param session: the active session to use | 
|  | 2428 | @param fwID: the unique ID of the fw version to delete | 
|  | 2429 | """ | 
|  | 2430 | fwID = args.versionID | 
|  | 2431 |  | 
|  | 2432 | print("Deleting version: "+fwID) | 
|  | 2433 | url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/action/Delete" | 
| Adriana Kobylak | 5af2fad | 2018-11-08 12:33:43 -0600 | [diff] [blame] | 2434 | data = "{\"data\": [] }" | 
|  | 2435 |  | 
|  | 2436 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2437 | res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Adriana Kobylak | 5af2fad | 2018-11-08 12:33:43 -0600 | [diff] [blame] | 2438 | except(requests.exceptions.Timeout): | 
|  | 2439 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2440 | if res.status_code == 200: | 
|  | 2441 | return ('The firmware version has been deleted') | 
|  | 2442 | else: | 
|  | 2443 | return ('Unable to delete the specified firmware version') | 
|  | 2444 |  | 
|  | 2445 |  | 
| Deepak Kodihalli | 22d4df0 | 2018-09-18 06:52:43 -0500 | [diff] [blame] | 2446 | def restLogging(host, args, session): | 
|  | 2447 | """ | 
|  | 2448 | Called by the logging function. Turns REST API logging on/off. | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2449 |  | 
| Deepak Kodihalli | 22d4df0 | 2018-09-18 06:52:43 -0500 | [diff] [blame] | 2450 | @param host: string, the hostname or IP address of the bmc | 
|  | 2451 | @param args: contains additional arguments used by the logging sub command | 
|  | 2452 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2453 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
| Deepak Kodihalli | 22d4df0 | 2018-09-18 06:52:43 -0500 | [diff] [blame] | 2454 | """ | 
| Deepak Kodihalli | 22d4df0 | 2018-09-18 06:52:43 -0500 | [diff] [blame] | 2455 | url="https://"+host+"/xyz/openbmc_project/logging/rest_api_logs/attr/Enabled" | 
| Deepak Kodihalli | 22d4df0 | 2018-09-18 06:52:43 -0500 | [diff] [blame] | 2456 |  | 
|  | 2457 | if(args.rest_logging == 'on'): | 
|  | 2458 | data = '{"data": 1}' | 
|  | 2459 | elif(args.rest_logging == 'off'): | 
|  | 2460 | data = '{"data": 0}' | 
|  | 2461 | else: | 
|  | 2462 | return "Invalid logging rest_api command" | 
|  | 2463 |  | 
|  | 2464 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2465 | res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Deepak Kodihalli | 22d4df0 | 2018-09-18 06:52:43 -0500 | [diff] [blame] | 2466 | except(requests.exceptions.Timeout): | 
|  | 2467 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2468 | return res.text | 
|  | 2469 |  | 
|  | 2470 |  | 
| Deepak Kodihalli | 02d5328 | 2018-09-18 06:53:31 -0500 | [diff] [blame] | 2471 | def remoteLogging(host, args, session): | 
|  | 2472 | """ | 
|  | 2473 | Called by the logging function. View config information for/disable remote logging (rsyslog). | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2474 |  | 
| Deepak Kodihalli | 02d5328 | 2018-09-18 06:53:31 -0500 | [diff] [blame] | 2475 | @param host: string, the hostname or IP address of the bmc | 
|  | 2476 | @param args: contains additional arguments used by the logging sub command | 
|  | 2477 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2478 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
| Deepak Kodihalli | 02d5328 | 2018-09-18 06:53:31 -0500 | [diff] [blame] | 2479 | """ | 
|  | 2480 |  | 
|  | 2481 | url="https://"+host+"/xyz/openbmc_project/logging/config/remote" | 
| Deepak Kodihalli | 02d5328 | 2018-09-18 06:53:31 -0500 | [diff] [blame] | 2482 |  | 
|  | 2483 | try: | 
|  | 2484 | if(args.remote_logging == 'view'): | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2485 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Deepak Kodihalli | 02d5328 | 2018-09-18 06:53:31 -0500 | [diff] [blame] | 2486 | elif(args.remote_logging == 'disable'): | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2487 | res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": 0}, verify=False, timeout=baseTimeout) | 
|  | 2488 | res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": ""}, verify=False, timeout=baseTimeout) | 
| Deepak Kodihalli | 02d5328 | 2018-09-18 06:53:31 -0500 | [diff] [blame] | 2489 | else: | 
|  | 2490 | return "Invalid logging remote_logging command" | 
|  | 2491 | except(requests.exceptions.Timeout): | 
|  | 2492 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2493 | return res.text | 
|  | 2494 |  | 
|  | 2495 |  | 
|  | 2496 | def remoteLoggingConfig(host, args, session): | 
|  | 2497 | """ | 
|  | 2498 | Called by the logging function. Configures remote logging (rsyslog). | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2499 |  | 
| Deepak Kodihalli | 02d5328 | 2018-09-18 06:53:31 -0500 | [diff] [blame] | 2500 | @param host: string, the hostname or IP address of the bmc | 
|  | 2501 | @param args: contains additional arguments used by the logging sub command | 
|  | 2502 | @param session: the active session to use | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 2503 | @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption | 
| Deepak Kodihalli | 02d5328 | 2018-09-18 06:53:31 -0500 | [diff] [blame] | 2504 | """ | 
|  | 2505 |  | 
|  | 2506 | url="https://"+host+"/xyz/openbmc_project/logging/config/remote" | 
| Deepak Kodihalli | 02d5328 | 2018-09-18 06:53:31 -0500 | [diff] [blame] | 2507 |  | 
|  | 2508 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2509 | res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": args.port}, verify=False, timeout=baseTimeout) | 
|  | 2510 | res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": args.address}, verify=False, timeout=baseTimeout) | 
| Deepak Kodihalli | 02d5328 | 2018-09-18 06:53:31 -0500 | [diff] [blame] | 2511 | except(requests.exceptions.Timeout): | 
|  | 2512 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2513 | return res.text | 
|  | 2514 |  | 
| Marri Devender Rao | 82590dc | 2019-06-06 04:54:22 -0500 | [diff] [blame^] | 2515 | def redfishSupportPresent(host, session): | 
|  | 2516 | url = "https://" + host + "/redfish/v1" | 
|  | 2517 | try: | 
|  | 2518 | resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
|  | 2519 | except(requests.exceptions.Timeout): | 
|  | 2520 | return False | 
|  | 2521 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2522 | return False | 
|  | 2523 | if resp.status_code != 200: | 
|  | 2524 | return False | 
|  | 2525 | else: | 
|  | 2526 | return True | 
| Ratan Gupta | 9166cd2 | 2018-10-01 18:09:40 +0530 | [diff] [blame] | 2527 |  | 
| Dhruvaraj Subhashchandran | 64e7f6f | 2018-10-02 03:42:14 -0500 | [diff] [blame] | 2528 | def certificateUpdate(host, args, session): | 
|  | 2529 | """ | 
|  | 2530 | Called by certificate management function. update server/client/authority certificates | 
|  | 2531 | Example: | 
|  | 2532 | certificate update server https -f cert.pem | 
|  | 2533 | certificate update authority ldap -f Root-CA.pem | 
|  | 2534 | certificate update client ldap -f cert.pem | 
|  | 2535 | @param host: string, the hostname or IP address of the bmc | 
|  | 2536 | @param args: contains additional arguments used by the certificate update sub command | 
|  | 2537 | @param session: the active session to use | 
|  | 2538 | """ | 
| Dhruvaraj Subhashchandran | 64e7f6f | 2018-10-02 03:42:14 -0500 | [diff] [blame] | 2539 | httpHeader = {'Content-Type': 'application/octet-stream'} | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 2540 | httpHeader.update(xAuthHeader) | 
| Dhruvaraj Subhashchandran | 64e7f6f | 2018-10-02 03:42:14 -0500 | [diff] [blame] | 2541 | data = open(args.fileloc, 'rb').read() | 
| Dhruvaraj Subhashchandran | 64e7f6f | 2018-10-02 03:42:14 -0500 | [diff] [blame] | 2542 | try: | 
| Marri Devender Rao | 82590dc | 2019-06-06 04:54:22 -0500 | [diff] [blame^] | 2543 | if redfishSupportPresent(host, session): | 
|  | 2544 | url = ""; | 
|  | 2545 | if(args.type.lower() == 'server'): | 
|  | 2546 | url = "https://" + host + \ | 
|  | 2547 | "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates" | 
|  | 2548 | elif(args.type.lower() == 'client'): | 
|  | 2549 | url = "https://" + host + \ | 
|  | 2550 | "/redfish/v1/AccountService/LDAP/Certificates" | 
|  | 2551 | elif(args.type.lower() == 'authority'): | 
|  | 2552 | url = "https://" + host + \ | 
|  | 2553 | "/redfish/v1/Managers/bmc/Truststore/Certificates" | 
|  | 2554 | else: | 
|  | 2555 | return "Unsupported certificate type" | 
|  | 2556 | resp = session.post(url, headers=httpHeader, data=data, | 
|  | 2557 | verify=False) | 
|  | 2558 | else: | 
|  | 2559 | url = "https://" + host + "/xyz/openbmc_project/certs/" + \ | 
|  | 2560 | args.type.lower() + "/" + args.service.lower() | 
|  | 2561 | resp = session.put(url, headers=httpHeader, data=data, verify=False) | 
| Dhruvaraj Subhashchandran | 64e7f6f | 2018-10-02 03:42:14 -0500 | [diff] [blame] | 2562 | except(requests.exceptions.Timeout): | 
|  | 2563 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2564 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2565 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2566 | if resp.status_code != 200: | 
|  | 2567 | print(resp.text) | 
|  | 2568 | return "Failed to update the certificate" | 
|  | 2569 | else: | 
| Marri Devender Rao | 82590dc | 2019-06-06 04:54:22 -0500 | [diff] [blame^] | 2570 | print("Update complete.") | 
| Dhruvaraj Subhashchandran | 64e7f6f | 2018-10-02 03:42:14 -0500 | [diff] [blame] | 2571 |  | 
|  | 2572 | def certificateDelete(host, args, session): | 
|  | 2573 | """ | 
|  | 2574 | Called by certificate management function to delete certificate | 
|  | 2575 | Example: | 
|  | 2576 | certificate delete server https | 
|  | 2577 | certificate delete authority ldap | 
|  | 2578 | certificate delete client ldap | 
|  | 2579 | @param host: string, the hostname or IP address of the bmc | 
|  | 2580 | @param args: contains additional arguments used by the certificate delete sub command | 
|  | 2581 | @param session: the active session to use | 
|  | 2582 | """ | 
|  | 2583 |  | 
|  | 2584 | httpHeader = {'Content-Type': 'multipart/form-data'} | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 2585 | httpHeader.update(xAuthHeader) | 
| Dhruvaraj Subhashchandran | 64e7f6f | 2018-10-02 03:42:14 -0500 | [diff] [blame] | 2586 | url = "https://" + host + "/xyz/openbmc_project/certs/" + args.type.lower() + "/" + args.service.lower() | 
|  | 2587 | print("Deleting certificate url=" + url) | 
|  | 2588 | try: | 
|  | 2589 | resp = session.delete(url, headers=httpHeader) | 
|  | 2590 | except(requests.exceptions.Timeout): | 
|  | 2591 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2592 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2593 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2594 | if resp.status_code != 200: | 
|  | 2595 | print(resp.text) | 
|  | 2596 | return "Failed to delete the certificate" | 
|  | 2597 | else: | 
|  | 2598 | print("Delete complete.") | 
|  | 2599 |  | 
| Deepak Kodihalli | 02d5328 | 2018-09-18 06:53:31 -0500 | [diff] [blame] | 2600 |  | 
| Ratan Gupta | 9166cd2 | 2018-10-01 18:09:40 +0530 | [diff] [blame] | 2601 | def enableLDAP(host, args, session): | 
|  | 2602 | """ | 
|  | 2603 | Called by the ldap function. Configures LDAP. | 
|  | 2604 |  | 
|  | 2605 | @param host: string, the hostname or IP address of the bmc | 
|  | 2606 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2607 | @param session: the active session to use | 
|  | 2608 | @param args.json: boolean, if this flag is set to true, the output will | 
|  | 2609 | be provided in json format for programmatic consumption | 
|  | 2610 | """ | 
|  | 2611 |  | 
|  | 2612 | url='https://'+host+'/xyz/openbmc_project/user/ldap/action/CreateConfig' | 
| Ratan Gupta | 9166cd2 | 2018-10-01 18:09:40 +0530 | [diff] [blame] | 2613 | scope = { | 
|  | 2614 | 'sub' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.sub', | 
|  | 2615 | 'one' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.one', | 
|  | 2616 | 'base': 'xyz.openbmc_project.User.Ldap.Create.SearchScope.base' | 
|  | 2617 | } | 
|  | 2618 |  | 
|  | 2619 | serverType = { | 
|  | 2620 | 'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Create.Type.ActiveDirectory', | 
|  | 2621 | 'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Create.Type.OpenLdap' | 
|  | 2622 | } | 
|  | 2623 |  | 
|  | 2624 | data = {"data": [args.uri, args.bindDN, args.baseDN, args.bindPassword, scope[args.scope], serverType[args.serverType]]} | 
|  | 2625 |  | 
|  | 2626 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2627 | res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout) | 
| Ratan Gupta | 9166cd2 | 2018-10-01 18:09:40 +0530 | [diff] [blame] | 2628 | except(requests.exceptions.Timeout): | 
|  | 2629 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2630 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2631 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2632 |  | 
|  | 2633 | return res.text | 
|  | 2634 |  | 
|  | 2635 |  | 
|  | 2636 | def disableLDAP(host, args, session): | 
|  | 2637 | """ | 
|  | 2638 | Called by the ldap function. Deletes the LDAP Configuration. | 
|  | 2639 |  | 
|  | 2640 | @param host: string, the hostname or IP address of the bmc | 
|  | 2641 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2642 | @param session: the active session to use | 
|  | 2643 | @param args.json: boolean, if this flag is set to true, the output | 
|  | 2644 | will be provided in json format for programmatic consumption | 
|  | 2645 | """ | 
|  | 2646 |  | 
|  | 2647 | url='https://'+host+'/xyz/openbmc_project/user/ldap/config/action/delete' | 
| Ratan Gupta | 9166cd2 | 2018-10-01 18:09:40 +0530 | [diff] [blame] | 2648 | data = {"data": []} | 
|  | 2649 |  | 
|  | 2650 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2651 | res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout) | 
| Ratan Gupta | 9166cd2 | 2018-10-01 18:09:40 +0530 | [diff] [blame] | 2652 | except(requests.exceptions.Timeout): | 
|  | 2653 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2654 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2655 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2656 |  | 
|  | 2657 | return res.text | 
|  | 2658 |  | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2659 |  | 
|  | 2660 | def enableDHCP(host, args, session): | 
|  | 2661 |  | 
|  | 2662 | """ | 
|  | 2663 | Called by the network function. Enables DHCP. | 
|  | 2664 |  | 
|  | 2665 | @param host: string, the hostname or IP address of the bmc | 
|  | 2666 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2667 | args.json: boolean, if this flag is set to true, the output | 
|  | 2668 | will be provided in json format for programmatic consumption | 
|  | 2669 | @param session: the active session to use | 
|  | 2670 | """ | 
|  | 2671 |  | 
|  | 2672 | url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\ | 
|  | 2673 | "/attr/DHCPEnabled" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2674 | data = "{\"data\": 1 }" | 
|  | 2675 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 2676 | res = session.put(url, headers=jsonHeader, data=data, verify=False, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2677 | timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2678 |  | 
|  | 2679 | except(requests.exceptions.Timeout): | 
|  | 2680 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2681 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2682 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2683 | if res.status_code == 403: | 
|  | 2684 | return "The specified Interface"+"("+args.Interface+")"+\ | 
|  | 2685 | " doesn't exist" | 
|  | 2686 |  | 
|  | 2687 | return res.text | 
|  | 2688 |  | 
|  | 2689 |  | 
|  | 2690 | def disableDHCP(host, args, session): | 
|  | 2691 | """ | 
|  | 2692 | Called by the network function. Disables DHCP. | 
|  | 2693 |  | 
|  | 2694 | @param host: string, the hostname or IP address of the bmc | 
|  | 2695 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2696 | args.json: boolean, if this flag is set to true, the output | 
|  | 2697 | will be provided in json format for programmatic consumption | 
|  | 2698 | @param session: the active session to use | 
|  | 2699 | """ | 
|  | 2700 |  | 
|  | 2701 | url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\ | 
|  | 2702 | "/attr/DHCPEnabled" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2703 | data = "{\"data\": 0 }" | 
|  | 2704 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 2705 | res = session.put(url, headers=jsonHeader, data=data, verify=False, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2706 | timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2707 | except(requests.exceptions.Timeout): | 
|  | 2708 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2709 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2710 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2711 | if res.status_code == 403: | 
|  | 2712 | return "The specified Interface"+"("+args.Interface+")"+\ | 
|  | 2713 | " doesn't exist" | 
|  | 2714 | return res.text | 
|  | 2715 |  | 
|  | 2716 |  | 
|  | 2717 | def getHostname(host, args, session): | 
|  | 2718 |  | 
|  | 2719 | """ | 
|  | 2720 | Called by the network function. Prints out the Hostname. | 
|  | 2721 |  | 
|  | 2722 | @param host: string, the hostname or IP address of the bmc | 
|  | 2723 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2724 | args.json: boolean, if this flag is set to true, the output | 
|  | 2725 | will be provided in json format for programmatic consumption | 
|  | 2726 | @param session: the active session to use | 
|  | 2727 | """ | 
|  | 2728 |  | 
|  | 2729 | url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2730 |  | 
|  | 2731 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2732 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2733 | except(requests.exceptions.Timeout): | 
|  | 2734 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2735 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2736 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2737 |  | 
|  | 2738 | return res.text | 
|  | 2739 |  | 
|  | 2740 |  | 
|  | 2741 | def setHostname(host, args, session): | 
|  | 2742 | """ | 
|  | 2743 | Called by the network function. Sets the Hostname. | 
|  | 2744 |  | 
|  | 2745 | @param host: string, the hostname or IP address of the bmc | 
|  | 2746 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2747 | args.json: boolean, if this flag is set to true, the output | 
|  | 2748 | will be provided in json format for programmatic consumption | 
|  | 2749 | @param session: the active session to use | 
|  | 2750 | """ | 
|  | 2751 |  | 
|  | 2752 | url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2753 |  | 
|  | 2754 | data = {"data": args.HostName} | 
|  | 2755 |  | 
|  | 2756 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 2757 | res = session.put(url, headers=jsonHeader, json=data, verify=False, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2758 | timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2759 | except(requests.exceptions.Timeout): | 
|  | 2760 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2761 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2762 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2763 |  | 
|  | 2764 | return res.text | 
|  | 2765 |  | 
|  | 2766 |  | 
|  | 2767 | def getDomainName(host, args, session): | 
|  | 2768 |  | 
|  | 2769 | """ | 
|  | 2770 | Called by the network function. Prints out the DomainName. | 
|  | 2771 |  | 
|  | 2772 | @param host: string, the hostname or IP address of the bmc | 
|  | 2773 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2774 | args.json: boolean, if this flag is set to true, the output | 
|  | 2775 | will be provided in json format for programmatic consumption | 
|  | 2776 | @param session: the active session to use | 
|  | 2777 | """ | 
|  | 2778 |  | 
|  | 2779 | url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\ | 
|  | 2780 | "/attr/DomainName" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2781 |  | 
|  | 2782 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2783 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2784 | except(requests.exceptions.Timeout): | 
|  | 2785 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2786 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2787 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2788 | if res.status_code == 404: | 
|  | 2789 | return "The specified Interface"+"("+args.Interface+")"+\ | 
|  | 2790 | " doesn't exist" | 
|  | 2791 |  | 
|  | 2792 | return res.text | 
|  | 2793 |  | 
|  | 2794 |  | 
|  | 2795 | def setDomainName(host, args, session): | 
|  | 2796 | """ | 
|  | 2797 | Called by the network function. Sets the DomainName. | 
|  | 2798 |  | 
|  | 2799 | @param host: string, the hostname or IP address of the bmc | 
|  | 2800 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2801 | args.json: boolean, if this flag is set to true, the output | 
|  | 2802 | will be provided in json format for programmatic consumption | 
|  | 2803 | @param session: the active session to use | 
|  | 2804 | """ | 
|  | 2805 |  | 
|  | 2806 | url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\ | 
|  | 2807 | "/attr/DomainName" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2808 |  | 
|  | 2809 | data = {"data": args.DomainName.split(",")} | 
|  | 2810 |  | 
|  | 2811 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 2812 | res = session.put(url, headers=jsonHeader, json=data, verify=False, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2813 | timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2814 | except(requests.exceptions.Timeout): | 
|  | 2815 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2816 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2817 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2818 | if res.status_code == 403: | 
|  | 2819 | return "The specified Interface"+"("+args.Interface+")"+\ | 
|  | 2820 | " doesn't exist" | 
|  | 2821 |  | 
|  | 2822 | return res.text | 
|  | 2823 |  | 
|  | 2824 |  | 
|  | 2825 | def getMACAddress(host, args, session): | 
|  | 2826 |  | 
|  | 2827 | """ | 
|  | 2828 | Called by the network function. Prints out the MACAddress. | 
|  | 2829 |  | 
|  | 2830 | @param host: string, the hostname or IP address of the bmc | 
|  | 2831 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2832 | args.json: boolean, if this flag is set to true, the output | 
|  | 2833 | will be provided in json format for programmatic consumption | 
|  | 2834 | @param session: the active session to use | 
|  | 2835 | """ | 
|  | 2836 |  | 
|  | 2837 | url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\ | 
|  | 2838 | "/attr/MACAddress" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2839 |  | 
|  | 2840 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2841 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2842 | except(requests.exceptions.Timeout): | 
|  | 2843 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2844 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2845 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2846 | if res.status_code == 404: | 
|  | 2847 | return "The specified Interface"+"("+args.Interface+")"+\ | 
|  | 2848 | " doesn't exist" | 
|  | 2849 |  | 
|  | 2850 | return res.text | 
|  | 2851 |  | 
|  | 2852 |  | 
|  | 2853 | def setMACAddress(host, args, session): | 
|  | 2854 | """ | 
|  | 2855 | Called by the network function. Sets the MACAddress. | 
|  | 2856 |  | 
|  | 2857 | @param host: string, the hostname or IP address of the bmc | 
|  | 2858 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2859 | args.json: boolean, if this flag is set to true, the output | 
|  | 2860 | will be provided in json format for programmatic consumption | 
|  | 2861 | @param session: the active session to use | 
|  | 2862 | """ | 
|  | 2863 |  | 
|  | 2864 | url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\ | 
|  | 2865 | "/attr/MACAddress" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2866 |  | 
|  | 2867 | data = {"data": args.MACAddress} | 
|  | 2868 |  | 
|  | 2869 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 2870 | res = session.put(url, headers=jsonHeader, json=data, verify=False, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2871 | timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2872 | except(requests.exceptions.Timeout): | 
|  | 2873 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2874 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2875 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2876 | if res.status_code == 403: | 
|  | 2877 | return "The specified Interface"+"("+args.Interface+")"+\ | 
|  | 2878 | " doesn't exist" | 
|  | 2879 |  | 
|  | 2880 | return res.text | 
|  | 2881 |  | 
|  | 2882 |  | 
|  | 2883 | def getDefaultGateway(host, args, session): | 
|  | 2884 |  | 
|  | 2885 | """ | 
|  | 2886 | Called by the network function. Prints out the DefaultGateway. | 
|  | 2887 |  | 
|  | 2888 | @param host: string, the hostname or IP address of the bmc | 
|  | 2889 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2890 | args.json: boolean, if this flag is set to true, the output | 
|  | 2891 | will be provided in json format for programmatic consumption | 
|  | 2892 | @param session: the active session to use | 
|  | 2893 | """ | 
|  | 2894 |  | 
|  | 2895 | url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2896 |  | 
|  | 2897 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2898 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2899 | except(requests.exceptions.Timeout): | 
|  | 2900 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2901 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2902 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2903 | if res.status_code == 404: | 
|  | 2904 | return "Failed to get Default Gateway info!!" | 
|  | 2905 |  | 
|  | 2906 | return res.text | 
|  | 2907 |  | 
|  | 2908 |  | 
|  | 2909 | def setDefaultGateway(host, args, session): | 
|  | 2910 | """ | 
|  | 2911 | Called by the network function. Sets the DefaultGateway. | 
|  | 2912 |  | 
|  | 2913 | @param host: string, the hostname or IP address of the bmc | 
|  | 2914 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2915 | args.json: boolean, if this flag is set to true, the output | 
|  | 2916 | will be provided in json format for programmatic consumption | 
|  | 2917 | @param session: the active session to use | 
|  | 2918 | """ | 
|  | 2919 |  | 
|  | 2920 | url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2921 |  | 
|  | 2922 | data = {"data": args.DefaultGW} | 
|  | 2923 |  | 
|  | 2924 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 2925 | res = session.put(url, headers=jsonHeader, json=data, verify=False, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2926 | timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2927 | except(requests.exceptions.Timeout): | 
|  | 2928 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2929 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2930 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2931 | if res.status_code == 403: | 
|  | 2932 | return "Failed to set Default Gateway!!" | 
|  | 2933 |  | 
|  | 2934 | return res.text | 
|  | 2935 |  | 
|  | 2936 |  | 
|  | 2937 | def viewNWConfig(host, args, session): | 
|  | 2938 | """ | 
|  | 2939 | Called by the ldap function. Prints out network configured properties | 
|  | 2940 |  | 
|  | 2941 | @param host: string, the hostname or IP address of the bmc | 
|  | 2942 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2943 | args.json: boolean, if this flag is set to true, the output | 
|  | 2944 | will be provided in json format for programmatic consumption | 
|  | 2945 | @param session: the active session to use | 
|  | 2946 | @return returns LDAP's configured properties. | 
|  | 2947 | """ | 
|  | 2948 | url = "https://"+host+"/xyz/openbmc_project/network/enumerate" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2949 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2950 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2951 | except(requests.exceptions.Timeout): | 
|  | 2952 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2953 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2954 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2955 | except(requests.exceptions.RequestException) as err: | 
|  | 2956 | return connectionErrHandler(args.json, "RequestException", err) | 
|  | 2957 | if res.status_code == 404: | 
|  | 2958 | return "LDAP server config has not been created" | 
|  | 2959 | return res.text | 
|  | 2960 |  | 
|  | 2961 |  | 
|  | 2962 | def getDNS(host, args, session): | 
|  | 2963 |  | 
|  | 2964 | """ | 
|  | 2965 | Called by the network function. Prints out DNS servers on the interface | 
|  | 2966 |  | 
|  | 2967 | @param host: string, the hostname or IP address of the bmc | 
|  | 2968 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2969 | args.json: boolean, if this flag is set to true, the output | 
|  | 2970 | will be provided in json format for programmatic consumption | 
|  | 2971 | @param session: the active session to use | 
|  | 2972 | """ | 
|  | 2973 |  | 
|  | 2974 | url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\ | 
|  | 2975 | + "/attr/Nameservers" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2976 |  | 
|  | 2977 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 2978 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 2979 | except(requests.exceptions.Timeout): | 
|  | 2980 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 2981 | except(requests.exceptions.ConnectionError) as err: | 
|  | 2982 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 2983 | if res.status_code == 404: | 
|  | 2984 | return "The specified Interface"+"("+args.Interface+")" + \ | 
|  | 2985 | " doesn't exist" | 
|  | 2986 |  | 
|  | 2987 | return res.text | 
|  | 2988 |  | 
|  | 2989 |  | 
|  | 2990 | def setDNS(host, args, session): | 
|  | 2991 | """ | 
|  | 2992 | Called by the network function. Sets DNS servers on the interface. | 
|  | 2993 |  | 
|  | 2994 | @param host: string, the hostname or IP address of the bmc | 
|  | 2995 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 2996 | args.json: boolean, if this flag is set to true, the output | 
|  | 2997 | will be provided in json format for programmatic consumption | 
|  | 2998 | @param session: the active session to use | 
|  | 2999 | """ | 
|  | 3000 |  | 
|  | 3001 | url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\ | 
|  | 3002 | + "/attr/Nameservers" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 3003 |  | 
|  | 3004 | data = {"data": args.DNSServers.split(",")} | 
|  | 3005 |  | 
|  | 3006 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 3007 | res = session.put(url, headers=jsonHeader, json=data, verify=False, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3008 | timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 3009 | except(requests.exceptions.Timeout): | 
|  | 3010 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3011 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3012 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3013 | if res.status_code == 403: | 
|  | 3014 | return "The specified Interface"+"("+args.Interface+")" +\ | 
|  | 3015 | " doesn't exist" | 
|  | 3016 |  | 
|  | 3017 | return res.text | 
|  | 3018 |  | 
|  | 3019 |  | 
|  | 3020 | def getNTP(host, args, session): | 
|  | 3021 |  | 
|  | 3022 | """ | 
|  | 3023 | Called by the network function. Prints out NTP servers on the interface | 
|  | 3024 |  | 
|  | 3025 | @param host: string, the hostname or IP address of the bmc | 
|  | 3026 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3027 | args.json: boolean, if this flag is set to true, the output | 
|  | 3028 | will be provided in json format for programmatic consumption | 
|  | 3029 | @param session: the active session to use | 
|  | 3030 | """ | 
|  | 3031 |  | 
|  | 3032 | url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\ | 
|  | 3033 | + "/attr/NTPServers" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 3034 |  | 
|  | 3035 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3036 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 3037 | except(requests.exceptions.Timeout): | 
|  | 3038 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3039 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3040 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3041 | if res.status_code == 404: | 
|  | 3042 | return "The specified Interface"+"("+args.Interface+")" + \ | 
|  | 3043 | " doesn't exist" | 
|  | 3044 |  | 
|  | 3045 | return res.text | 
|  | 3046 |  | 
|  | 3047 |  | 
|  | 3048 | def setNTP(host, args, session): | 
|  | 3049 | """ | 
|  | 3050 | Called by the network function. Sets NTP servers on the interface. | 
|  | 3051 |  | 
|  | 3052 | @param host: string, the hostname or IP address of the bmc | 
|  | 3053 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3054 | args.json: boolean, if this flag is set to true, the output | 
|  | 3055 | will be provided in json format for programmatic consumption | 
|  | 3056 | @param session: the active session to use | 
|  | 3057 | """ | 
|  | 3058 |  | 
|  | 3059 | url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\ | 
|  | 3060 | + "/attr/NTPServers" | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 3061 |  | 
|  | 3062 | data = {"data": args.NTPServers.split(",")} | 
|  | 3063 |  | 
|  | 3064 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 3065 | res = session.put(url, headers=jsonHeader, json=data, verify=False, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3066 | timeout=baseTimeout) | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 3067 | except(requests.exceptions.Timeout): | 
|  | 3068 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3069 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3070 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3071 | if res.status_code == 403: | 
|  | 3072 | return "The specified Interface"+"("+args.Interface+")" +\ | 
|  | 3073 | " doesn't exist" | 
|  | 3074 |  | 
|  | 3075 | return res.text | 
|  | 3076 |  | 
|  | 3077 |  | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 3078 | def addIP(host, args, session): | 
|  | 3079 | """ | 
|  | 3080 | Called by the network function. Configures IP address on given interface | 
|  | 3081 |  | 
|  | 3082 | @param host: string, the hostname or IP address of the bmc | 
|  | 3083 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3084 | args.json: boolean, if this flag is set to true, the output | 
|  | 3085 | will be provided in json format for programmatic consumption | 
|  | 3086 | @param session: the active session to use | 
|  | 3087 | """ | 
|  | 3088 |  | 
|  | 3089 | url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\ | 
|  | 3090 | + "/action/IP" | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 3091 | protocol = { | 
|  | 3092 | 'ipv4': 'xyz.openbmc_project.Network.IP.Protocol.IPv4', | 
|  | 3093 | 'ipv6': 'xyz.openbmc_project.Network.IP.Protocol.IPv6' | 
|  | 3094 | } | 
|  | 3095 |  | 
|  | 3096 | data = {"data": [protocol[args.type], args.address, int(args.prefixLength), | 
|  | 3097 | args.gateway]} | 
|  | 3098 |  | 
|  | 3099 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 3100 | res = session.post(url, headers=jsonHeader, json=data, verify=False, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3101 | timeout=baseTimeout) | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 3102 | except(requests.exceptions.Timeout): | 
|  | 3103 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3104 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3105 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3106 | if res.status_code == 404: | 
|  | 3107 | return "The specified Interface" + "(" + args.Interface + ")" +\ | 
|  | 3108 | " doesn't exist" | 
|  | 3109 |  | 
|  | 3110 | return res.text | 
|  | 3111 |  | 
|  | 3112 |  | 
|  | 3113 | def getIP(host, args, session): | 
|  | 3114 | """ | 
|  | 3115 | Called by the network function. Prints out IP address of given interface | 
|  | 3116 |  | 
|  | 3117 | @param host: string, the hostname or IP address of the bmc | 
|  | 3118 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3119 | args.json: boolean, if this flag is set to true, the output | 
|  | 3120 | will be provided in json format for programmatic consumption | 
|  | 3121 | @param session: the active session to use | 
|  | 3122 | """ | 
|  | 3123 |  | 
|  | 3124 | url = "https://" + host+"/xyz/openbmc_project/network/" + args.Interface +\ | 
|  | 3125 | "/enumerate" | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 3126 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3127 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 3128 | except(requests.exceptions.Timeout): | 
|  | 3129 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3130 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3131 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3132 | if res.status_code == 404: | 
|  | 3133 | return "The specified Interface" + "(" + args.Interface + ")" +\ | 
|  | 3134 | " doesn't exist" | 
|  | 3135 |  | 
|  | 3136 | return res.text | 
|  | 3137 |  | 
|  | 3138 |  | 
|  | 3139 | def deleteIP(host, args, session): | 
|  | 3140 | """ | 
|  | 3141 | Called by the network function. Deletes the IP address from given Interface | 
|  | 3142 |  | 
|  | 3143 | @param host: string, the hostname or IP address of the bmc | 
|  | 3144 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3145 | @param session: the active session to use | 
|  | 3146 | @param args.json: boolean, if this flag is set to true, the output | 
|  | 3147 | will be provided in json format for programmatic consumption | 
|  | 3148 | """ | 
|  | 3149 |  | 
|  | 3150 | url = "https://"+host+"/xyz/openbmc_project/network/" + args.Interface+\ | 
|  | 3151 | "/enumerate" | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 3152 | data = {"data": []} | 
|  | 3153 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3154 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 3155 | except(requests.exceptions.Timeout): | 
|  | 3156 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3157 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3158 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3159 | if res.status_code == 404: | 
|  | 3160 | return "The specified Interface" + "(" + args.Interface + ")" +\ | 
|  | 3161 | " doesn't exist" | 
|  | 3162 | objDict = json.loads(res.text) | 
|  | 3163 | if not objDict['data']: | 
|  | 3164 | return "No object found for given address on given Interface" | 
|  | 3165 |  | 
|  | 3166 | for obj in objDict['data']: | 
|  | 3167 | if args.address in objDict['data'][obj]['Address']: | 
|  | 3168 | url = "https://"+host+obj+"/action/delete" | 
|  | 3169 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 3170 | res = session.post(url, headers=jsonHeader, json=data, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3171 | verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 3172 | except(requests.exceptions.Timeout): | 
|  | 3173 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3174 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3175 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3176 | return res.text | 
|  | 3177 | else: | 
|  | 3178 | continue | 
|  | 3179 | return "No object found for given address on given Interface" | 
|  | 3180 |  | 
|  | 3181 |  | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3182 | def addVLAN(host, args, session): | 
|  | 3183 | """ | 
|  | 3184 | Called by the network function. Creates VLAN on given interface. | 
|  | 3185 |  | 
|  | 3186 | @param host: string, the hostname or IP address of the bmc | 
|  | 3187 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3188 | args.json: boolean, if this flag is set to true, the output | 
|  | 3189 | will be provided in json format for programmatic consumption | 
|  | 3190 | @param session: the active session to use | 
|  | 3191 | """ | 
|  | 3192 |  | 
|  | 3193 | url = "https://" + host+"/xyz/openbmc_project/network/action/VLAN" | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3194 |  | 
|  | 3195 | data = {"data": [args.Interface,args.Identifier]} | 
|  | 3196 |  | 
|  | 3197 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 3198 | res = session.post(url, headers=jsonHeader, json=data, verify=False, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3199 | timeout=baseTimeout) | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3200 | except(requests.exceptions.Timeout): | 
|  | 3201 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3202 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3203 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3204 | if res.status_code == 400: | 
|  | 3205 | return "The specified Interface" + "(" + args.Interface + ")" +\ | 
|  | 3206 | " doesn't exist" | 
|  | 3207 |  | 
|  | 3208 | return res.text | 
|  | 3209 |  | 
|  | 3210 |  | 
|  | 3211 | def deleteVLAN(host, args, session): | 
|  | 3212 | """ | 
|  | 3213 | Called by the network function. Creates VLAN on given interface. | 
|  | 3214 |  | 
|  | 3215 | @param host: string, the hostname or IP address of the bmc | 
|  | 3216 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3217 | args.json: boolean, if this flag is set to true, the output | 
|  | 3218 | will be provided in json format for programmatic consumption | 
|  | 3219 | @param session: the active session to use | 
|  | 3220 | """ | 
|  | 3221 |  | 
|  | 3222 | url = "https://" + host+"/xyz/openbmc_project/network/"+args.Interface+"/action/delete" | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3223 | data = {"data": []} | 
|  | 3224 |  | 
|  | 3225 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3226 | res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3227 | except(requests.exceptions.Timeout): | 
|  | 3228 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3229 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3230 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3231 | if res.status_code == 404: | 
|  | 3232 | return "The specified VLAN"+"("+args.Interface+"_"+args.Identifier\ | 
|  | 3233 | +")" +" doesn't exist" | 
|  | 3234 |  | 
|  | 3235 | return res.text | 
|  | 3236 |  | 
|  | 3237 |  | 
|  | 3238 | def viewDHCPConfig(host, args, session): | 
|  | 3239 | """ | 
|  | 3240 | Called by the network function. Shows DHCP configured Properties. | 
|  | 3241 |  | 
|  | 3242 | @param host: string, the hostname or IP address of the bmc | 
|  | 3243 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3244 | args.json: boolean, if this flag is set to true, the output | 
|  | 3245 | will be provided in json format for programmatic consumption | 
|  | 3246 | @param session: the active session to use | 
|  | 3247 | """ | 
|  | 3248 |  | 
|  | 3249 | url="https://"+host+"/xyz/openbmc_project/network/config/dhcp" | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3250 |  | 
|  | 3251 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3252 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3253 | except(requests.exceptions.Timeout): | 
|  | 3254 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3255 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3256 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3257 |  | 
|  | 3258 | return res.text | 
|  | 3259 |  | 
|  | 3260 |  | 
|  | 3261 | def configureDHCP(host, args, session): | 
|  | 3262 | """ | 
|  | 3263 | Called by the network function. Configures/updates DHCP Properties. | 
|  | 3264 |  | 
|  | 3265 | @param host: string, the hostname or IP address of the bmc | 
|  | 3266 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3267 | args.json: boolean, if this flag is set to true, the output | 
|  | 3268 | will be provided in json format for programmatic consumption | 
|  | 3269 | @param session: the active session to use | 
|  | 3270 | """ | 
|  | 3271 |  | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3272 |  | 
|  | 3273 | try: | 
|  | 3274 | url="https://"+host+"/xyz/openbmc_project/network/config/dhcp" | 
|  | 3275 | if(args.DNSEnabled == True): | 
|  | 3276 | data = '{"data": 1}' | 
|  | 3277 | else: | 
|  | 3278 | data = '{"data": 0}' | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 3279 | res = session.put(url + '/attr/DNSEnabled', headers=jsonHeader, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3280 | data=data, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3281 | if(args.HostNameEnabled == True): | 
|  | 3282 | data = '{"data": 1}' | 
|  | 3283 | else: | 
|  | 3284 | data = '{"data": 0}' | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 3285 | res = session.put(url + '/attr/HostNameEnabled', headers=jsonHeader, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3286 | data=data, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3287 | if(args.NTPEnabled == True): | 
|  | 3288 | data = '{"data": 1}' | 
|  | 3289 | else: | 
|  | 3290 | data = '{"data": 0}' | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 3291 | res = session.put(url + '/attr/NTPEnabled', headers=jsonHeader, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3292 | data=data, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3293 | if(args.SendHostNameEnabled == True): | 
|  | 3294 | data = '{"data": 1}' | 
|  | 3295 | else: | 
|  | 3296 | data = '{"data": 0}' | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 3297 | res = session.put(url + '/attr/SendHostNameEnabled', headers=jsonHeader, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3298 | data=data, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3299 | except(requests.exceptions.Timeout): | 
|  | 3300 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3301 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3302 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3303 |  | 
|  | 3304 | return res.text | 
|  | 3305 |  | 
|  | 3306 |  | 
|  | 3307 | def nwReset(host, args, session): | 
|  | 3308 |  | 
|  | 3309 | """ | 
|  | 3310 | Called by the network function. Resets networks setting to factory defaults. | 
|  | 3311 |  | 
|  | 3312 | @param host: string, the hostname or IP address of the bmc | 
|  | 3313 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3314 | args.json: boolean, if this flag is set to true, the output | 
|  | 3315 | will be provided in json format for programmatic consumption | 
|  | 3316 | @param session: the active session to use | 
|  | 3317 | """ | 
|  | 3318 |  | 
|  | 3319 | url = "https://"+host+"/xyz/openbmc_project/network/action/Reset" | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3320 | data = '{"data":[] }' | 
|  | 3321 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 3322 | res = session.post(url, headers=jsonHeader, data=data, verify=False, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3323 | timeout=baseTimeout) | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3324 |  | 
|  | 3325 | except(requests.exceptions.Timeout): | 
|  | 3326 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3327 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3328 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3329 |  | 
|  | 3330 | return res.text | 
|  | 3331 |  | 
|  | 3332 |  | 
| Ratan Gupta | feee637 | 2018-10-17 23:25:51 +0530 | [diff] [blame] | 3333 | def createPrivilegeMapping(host, args, session): | 
|  | 3334 | """ | 
|  | 3335 | Called by the ldap function. Creates the group and the privilege mapping. | 
|  | 3336 |  | 
|  | 3337 | @param host: string, the hostname or IP address of the bmc | 
|  | 3338 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3339 | @param session: the active session to use | 
|  | 3340 | @param args.json: boolean, if this flag is set to true, the output | 
|  | 3341 | will be provided in json format for programmatic consumption | 
|  | 3342 | """ | 
|  | 3343 |  | 
|  | 3344 | url = 'https://'+host+'/xyz/openbmc_project/user/ldap/action/Create' | 
| Ratan Gupta | feee637 | 2018-10-17 23:25:51 +0530 | [diff] [blame] | 3345 |  | 
|  | 3346 | data = {"data": [args.groupName,args.privilege]} | 
|  | 3347 |  | 
|  | 3348 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3349 | res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout) | 
| Ratan Gupta | feee637 | 2018-10-17 23:25:51 +0530 | [diff] [blame] | 3350 | except(requests.exceptions.Timeout): | 
|  | 3351 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3352 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3353 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3354 | return res.text | 
|  | 3355 |  | 
|  | 3356 | def listPrivilegeMapping(host, args, session): | 
|  | 3357 | """ | 
|  | 3358 | Called by the ldap function. Lists the group and the privilege mapping. | 
|  | 3359 |  | 
|  | 3360 | @param host: string, the hostname or IP address of the bmc | 
|  | 3361 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3362 | @param session: the active session to use | 
|  | 3363 | @param args.json: boolean, if this flag is set to true, the output | 
|  | 3364 | will be provided in json format for programmatic consumption | 
|  | 3365 | """ | 
|  | 3366 | url = 'https://'+host+'/xyz/openbmc_project/user/ldap/enumerate' | 
| Ratan Gupta | feee637 | 2018-10-17 23:25:51 +0530 | [diff] [blame] | 3367 | data = {"data": []} | 
|  | 3368 |  | 
|  | 3369 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3370 | res = session.get(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout) | 
| Ratan Gupta | feee637 | 2018-10-17 23:25:51 +0530 | [diff] [blame] | 3371 | except(requests.exceptions.Timeout): | 
|  | 3372 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3373 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3374 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3375 | return res.text | 
|  | 3376 |  | 
|  | 3377 | def deletePrivilegeMapping(host, args, session): | 
|  | 3378 | """ | 
|  | 3379 | Called by the ldap function. Deletes the mapping associated with the group. | 
|  | 3380 |  | 
|  | 3381 | @param host: string, the hostname or IP address of the bmc | 
|  | 3382 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3383 | @param session: the active session to use | 
|  | 3384 | @param args.json: boolean, if this flag is set to true, the output | 
|  | 3385 | will be provided in json format for programmatic consumption | 
|  | 3386 | """ | 
|  | 3387 | (ldapNameSpaceObjects) = listPrivilegeMapping(host, args, session) | 
|  | 3388 | ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"] | 
|  | 3389 | path = '' | 
|  | 3390 |  | 
|  | 3391 | # not interested in the config objet | 
|  | 3392 | ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None) | 
|  | 3393 |  | 
|  | 3394 | # search for the object having the mapping for the given group | 
|  | 3395 | for key,value in ldapNameSpaceObjects.items(): | 
|  | 3396 | if value['GroupName'] == args.groupName: | 
|  | 3397 | path = key | 
|  | 3398 | break | 
|  | 3399 |  | 
|  | 3400 | if path == '': | 
|  | 3401 | return "No privilege mapping found for this group." | 
|  | 3402 |  | 
|  | 3403 | # delete the object | 
|  | 3404 | url = 'https://'+host+path+'/action/delete' | 
| Ratan Gupta | feee637 | 2018-10-17 23:25:51 +0530 | [diff] [blame] | 3405 | data = {"data": []} | 
|  | 3406 |  | 
|  | 3407 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3408 | res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout) | 
| Ratan Gupta | feee637 | 2018-10-17 23:25:51 +0530 | [diff] [blame] | 3409 | except(requests.exceptions.Timeout): | 
|  | 3410 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3411 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3412 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3413 | return res.text | 
| Ratan Gupta | 9166cd2 | 2018-10-01 18:09:40 +0530 | [diff] [blame] | 3414 |  | 
| Sivas SRR | 7883527 | 2018-11-27 05:27:19 -0600 | [diff] [blame] | 3415 | def deleteAllPrivilegeMapping(host, args, session): | 
|  | 3416 | """ | 
|  | 3417 | Called by the ldap function. Deletes all the privilege mapping and group defined. | 
|  | 3418 | @param host: string, the hostname or IP address of the bmc | 
|  | 3419 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3420 | @param session: the active session to use | 
|  | 3421 | @param args.json: boolean, if this flag is set to true, the output | 
|  | 3422 | will be provided in json format for programmatic consumption | 
|  | 3423 | """ | 
|  | 3424 | ldapNameSpaceObjects = listPrivilegeMapping(host, args, session) | 
|  | 3425 | ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"] | 
|  | 3426 | path = '' | 
|  | 3427 |  | 
|  | 3428 | # Remove the config object. | 
|  | 3429 | ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None) | 
| Sivas SRR | 7883527 | 2018-11-27 05:27:19 -0600 | [diff] [blame] | 3430 | data = {"data": []} | 
|  | 3431 |  | 
|  | 3432 | try: | 
|  | 3433 | # search for GroupName property and delete if it is available. | 
|  | 3434 | for path in ldapNameSpaceObjects.keys(): | 
|  | 3435 | # delete the object | 
|  | 3436 | url = 'https://'+host+path+'/action/delete' | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3437 | res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout) | 
| Sivas SRR | 7883527 | 2018-11-27 05:27:19 -0600 | [diff] [blame] | 3438 | except(requests.exceptions.Timeout): | 
|  | 3439 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3440 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3441 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3442 | return res.text | 
|  | 3443 |  | 
| Nagaraju Goruganti | 7d1fe17 | 2018-11-13 06:09:29 -0600 | [diff] [blame] | 3444 | def viewLDAPConfig(host, args, session): | 
|  | 3445 | """ | 
|  | 3446 | Called by the ldap function. Prints out LDAP's configured properties | 
|  | 3447 |  | 
|  | 3448 | @param host: string, the hostname or IP address of the bmc | 
|  | 3449 | @param args: contains additional arguments used by the ldap subcommand | 
|  | 3450 | args.json: boolean, if this flag is set to true, the output | 
|  | 3451 | will be provided in json format for programmatic consumption | 
|  | 3452 | @param session: the active session to use | 
|  | 3453 | @return returns LDAP's configured properties. | 
|  | 3454 | """ | 
|  | 3455 | url = "https://"+host+"/xyz/openbmc_project/user/ldap/config" | 
| Nagaraju Goruganti | 7d1fe17 | 2018-11-13 06:09:29 -0600 | [diff] [blame] | 3456 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3457 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Nagaraju Goruganti | 7d1fe17 | 2018-11-13 06:09:29 -0600 | [diff] [blame] | 3458 | 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 | except(requests.exceptions.RequestException) as err: | 
|  | 3463 | return connectionErrHandler(args.json, "RequestException", err) | 
|  | 3464 | if res.status_code == 404: | 
|  | 3465 | return "LDAP server config has not been created" | 
|  | 3466 | return res.text | 
|  | 3467 |  | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 3468 | def str2bool(v): | 
|  | 3469 | if v.lower() in ('yes', 'true', 't', 'y', '1'): | 
|  | 3470 | return True | 
|  | 3471 | elif v.lower() in ('no', 'false', 'f', 'n', '0'): | 
|  | 3472 | return False | 
|  | 3473 | else: | 
|  | 3474 | raise argparse.ArgumentTypeError('Boolean value expected.') | 
| Nagaraju Goruganti | 7d1fe17 | 2018-11-13 06:09:29 -0600 | [diff] [blame] | 3475 |  | 
| Matt Spinler | 7d426c2 | 2018-09-24 14:42:07 -0500 | [diff] [blame] | 3476 | def localUsers(host, args, session): | 
|  | 3477 | """ | 
|  | 3478 | Enables and disables local BMC users. | 
|  | 3479 |  | 
|  | 3480 | @param host: string, the hostname or IP address of the bmc | 
|  | 3481 | @param args: contains additional arguments used by the logging sub command | 
|  | 3482 | @param session: the active session to use | 
|  | 3483 | """ | 
|  | 3484 |  | 
| Matt Spinler | 7d426c2 | 2018-09-24 14:42:07 -0500 | [diff] [blame] | 3485 | url="https://{hostname}/xyz/openbmc_project/user/enumerate".format(hostname=host) | 
|  | 3486 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3487 | res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout) | 
| Matt Spinler | 7d426c2 | 2018-09-24 14:42:07 -0500 | [diff] [blame] | 3488 | except(requests.exceptions.Timeout): | 
|  | 3489 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3490 | usersDict = json.loads(res.text) | 
|  | 3491 |  | 
|  | 3492 | if not usersDict['data']: | 
|  | 3493 | return "No users found" | 
|  | 3494 |  | 
|  | 3495 | output = "" | 
|  | 3496 | for user in usersDict['data']: | 
| Matt Spinler | 015adc2 | 2018-10-23 14:30:19 -0500 | [diff] [blame] | 3497 |  | 
|  | 3498 | # Skip LDAP and another non-local users | 
|  | 3499 | if 'UserEnabled' not in usersDict['data'][user]: | 
|  | 3500 | continue | 
|  | 3501 |  | 
| Matt Spinler | 7d426c2 | 2018-09-24 14:42:07 -0500 | [diff] [blame] | 3502 | name = user.split('/')[-1] | 
|  | 3503 | url = "https://{hostname}{user}/attr/UserEnabled".format(hostname=host, user=user) | 
|  | 3504 |  | 
|  | 3505 | if args.local_users == "queryenabled": | 
|  | 3506 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3507 | res = session.get(url, headers=jsonHeader,verify=False, timeout=baseTimeout) | 
| Matt Spinler | 7d426c2 | 2018-09-24 14:42:07 -0500 | [diff] [blame] | 3508 | except(requests.exceptions.Timeout): | 
|  | 3509 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3510 |  | 
|  | 3511 | result = json.loads(res.text) | 
|  | 3512 | output += ("User: {name}  Enabled: {result}\n").format(name=name, result=result['data']) | 
|  | 3513 |  | 
|  | 3514 | elif args.local_users in ["enableall", "disableall"]: | 
|  | 3515 | action = "" | 
|  | 3516 | if args.local_users == "enableall": | 
|  | 3517 | data = '{"data": true}' | 
|  | 3518 | action = "Enabling" | 
|  | 3519 | else: | 
|  | 3520 | data = '{"data": false}' | 
|  | 3521 | action = "Disabling" | 
|  | 3522 |  | 
|  | 3523 | output += "{action} {name}\n".format(action=action, name=name) | 
|  | 3524 |  | 
|  | 3525 | try: | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3526 | resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout) | 
| Matt Spinler | 7d426c2 | 2018-09-24 14:42:07 -0500 | [diff] [blame] | 3527 | except(requests.exceptions.Timeout): | 
|  | 3528 | return connectionErrHandler(args.json, "Timeout", None) | 
|  | 3529 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3530 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3531 | else: | 
|  | 3532 | return "Invalid local users argument" | 
|  | 3533 |  | 
|  | 3534 | return output | 
|  | 3535 |  | 
| Marri Devender Rao | 2c2a516 | 2018-11-05 08:57:11 -0600 | [diff] [blame] | 3536 | def setPassword(host, args, session): | 
|  | 3537 | """ | 
|  | 3538 | Set local user password | 
|  | 3539 | @param host: string, the hostname or IP address of the bmc | 
|  | 3540 | @param args: contains additional arguments used by the logging sub | 
|  | 3541 | command | 
|  | 3542 | @param session: the active session to use | 
|  | 3543 | @param args.json: boolean, if this flag is set to true, the output | 
|  | 3544 | will be provided in json format for programmatic consumption | 
|  | 3545 | @return: Session object | 
|  | 3546 | """ | 
|  | 3547 | url = "https://" + host + "/xyz/openbmc_project/user/" + args.user + \ | 
|  | 3548 | "/action/SetPassword" | 
| Marri Devender Rao | 2c2a516 | 2018-11-05 08:57:11 -0600 | [diff] [blame] | 3549 | try: | 
| Matt Spinler | 220c3c4 | 2019-01-04 15:09:29 -0600 | [diff] [blame] | 3550 | res = session.post(url, headers=jsonHeader, | 
| Marri Devender Rao | 2c2a516 | 2018-11-05 08:57:11 -0600 | [diff] [blame] | 3551 | json={"data": [args.password]}, verify=False, | 
| Justin Thaler | 2719762 | 2019-01-23 14:42:11 -0600 | [diff] [blame] | 3552 | timeout=baseTimeout) | 
| Marri Devender Rao | 2c2a516 | 2018-11-05 08:57:11 -0600 | [diff] [blame] | 3553 | except(requests.exceptions.Timeout): | 
|  | 3554 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3555 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3556 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3557 | except(requests.exceptions.RequestException) as err: | 
|  | 3558 | return connectionErrHandler(args.json, "RequestException", err) | 
|  | 3559 | return res.text | 
|  | 3560 |  | 
| Matthew Barth | 368e83c | 2019-02-01 13:48:25 -0600 | [diff] [blame] | 3561 |  | 
|  | 3562 | def getThermalZones(host, args, session): | 
|  | 3563 | """ | 
|  | 3564 | Get the available thermal control zones | 
|  | 3565 | @param host: string, the hostname or IP address of the bmc | 
|  | 3566 | @param args: contains additional arguments used to get the thermal | 
|  | 3567 | control zones | 
|  | 3568 | @param session: the active session to use | 
|  | 3569 | @return: Session object | 
|  | 3570 | """ | 
|  | 3571 | url = "https://" + host + "/xyz/openbmc_project/control/thermal/enumerate" | 
|  | 3572 |  | 
|  | 3573 | try: | 
|  | 3574 | res = session.get(url, headers=jsonHeader, verify=False, timeout=30) | 
|  | 3575 | except(requests.exceptions.Timeout): | 
|  | 3576 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3577 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3578 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3579 | except(requests.exceptions.RequestException) as err: | 
|  | 3580 | return connectionErrHandler(args.json, "RequestException", err) | 
|  | 3581 |  | 
|  | 3582 | if (res.status_code == 404): | 
|  | 3583 | return "No thermal control zones found or system is in a" + \ | 
|  | 3584 | " powered off state" | 
|  | 3585 |  | 
|  | 3586 | zonesDict = json.loads(res.text) | 
|  | 3587 | if not zonesDict['data']: | 
|  | 3588 | return "No thermal control zones found" | 
|  | 3589 | for zone in zonesDict['data']: | 
|  | 3590 | z = ",".join(str(zone.split('/')[-1]) for zone in zonesDict['data']) | 
|  | 3591 |  | 
|  | 3592 | return "Zones: [ " + z + " ]" | 
|  | 3593 |  | 
|  | 3594 |  | 
|  | 3595 | def getThermalMode(host, args, session): | 
|  | 3596 | """ | 
|  | 3597 | Get thermal control mode | 
|  | 3598 | @param host: string, the hostname or IP address of the bmc | 
|  | 3599 | @param args: contains additional arguments used to get the thermal | 
|  | 3600 | control mode | 
|  | 3601 | @param session: the active session to use | 
|  | 3602 | @param args.zone: the zone to get the mode on | 
|  | 3603 | @return: Session object | 
|  | 3604 | """ | 
|  | 3605 | url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \ | 
|  | 3606 | args.zone | 
|  | 3607 |  | 
|  | 3608 | try: | 
|  | 3609 | res = session.get(url, headers=jsonHeader, verify=False, timeout=30) | 
|  | 3610 | except(requests.exceptions.Timeout): | 
|  | 3611 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3612 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3613 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3614 | except(requests.exceptions.RequestException) as err: | 
|  | 3615 | return connectionErrHandler(args.json, "RequestException", err) | 
|  | 3616 |  | 
|  | 3617 | if (res.status_code == 404): | 
|  | 3618 | return "Thermal control zone(" + args.zone + ") not found or" + \ | 
|  | 3619 | " system is in a powered off state" | 
|  | 3620 |  | 
|  | 3621 | propsDict = json.loads(res.text) | 
|  | 3622 | if not propsDict['data']: | 
|  | 3623 | return "No thermal control properties found on zone(" + args.zone + ")" | 
|  | 3624 | curMode = "Current" | 
|  | 3625 | supModes = "Supported" | 
|  | 3626 | result = "\n" | 
|  | 3627 | for prop in propsDict['data']: | 
|  | 3628 | if (prop.casefold() == curMode.casefold()): | 
|  | 3629 | result += curMode + " Mode: " + propsDict['data'][curMode] + "\n" | 
|  | 3630 | if (prop.casefold() == supModes.casefold()): | 
|  | 3631 | s = ", ".join(str(sup) for sup in propsDict['data'][supModes]) | 
|  | 3632 | result += supModes + " Modes: [ " + s + " ]\n" | 
|  | 3633 |  | 
|  | 3634 | return result | 
|  | 3635 |  | 
|  | 3636 | def setThermalMode(host, args, session): | 
|  | 3637 | """ | 
|  | 3638 | Set thermal control mode | 
|  | 3639 | @param host: string, the hostname or IP address of the bmc | 
|  | 3640 | @param args: contains additional arguments used for setting the thermal | 
|  | 3641 | control mode | 
|  | 3642 | @param session: the active session to use | 
|  | 3643 | @param args.zone: the zone to set the mode on | 
|  | 3644 | @param args.mode: the mode to enable | 
|  | 3645 | @return: Session object | 
|  | 3646 | """ | 
|  | 3647 | url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \ | 
|  | 3648 | args.zone + "/attr/Current" | 
|  | 3649 |  | 
|  | 3650 | # Check args.mode against supported modes using `getThermalMode` output | 
|  | 3651 | modes = getThermalMode(host, args, session) | 
|  | 3652 | modes = os.linesep.join([m for m in modes.splitlines() if m]) | 
|  | 3653 | modes = modes.replace("\n", ";").strip() | 
|  | 3654 | modesDict = dict(m.split(': ') for m in modes.split(';')) | 
|  | 3655 | sModes = ''.join(s for s in modesDict['Supported Modes'] if s not in '[ ]') | 
|  | 3656 | if args.mode.casefold() not in \ | 
|  | 3657 | (m.casefold() for m in sModes.split(',')) or not args.mode: | 
|  | 3658 | result = ("Unsupported mode('" + args.mode + "') given, " + | 
|  | 3659 | "select a supported mode: \n" + | 
|  | 3660 | getThermalMode(host, args, session)) | 
|  | 3661 | return result | 
|  | 3662 |  | 
|  | 3663 | data = '{"data":"' + args.mode + '"}' | 
|  | 3664 | try: | 
|  | 3665 | res = session.get(url, headers=jsonHeader, verify=False, timeout=30) | 
|  | 3666 | except(requests.exceptions.Timeout): | 
|  | 3667 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3668 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3669 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3670 | except(requests.exceptions.RequestException) as err: | 
|  | 3671 | return connectionErrHandler(args.json, "RequestException", err) | 
|  | 3672 |  | 
|  | 3673 | if (data and res.status_code != 404): | 
|  | 3674 | try: | 
|  | 3675 | res = session.put(url, headers=jsonHeader, | 
|  | 3676 | data=data, verify=False, | 
|  | 3677 | timeout=30) | 
|  | 3678 | except(requests.exceptions.Timeout): | 
|  | 3679 | return(connectionErrHandler(args.json, "Timeout", None)) | 
|  | 3680 | except(requests.exceptions.ConnectionError) as err: | 
|  | 3681 | return connectionErrHandler(args.json, "ConnectionError", err) | 
|  | 3682 | except(requests.exceptions.RequestException) as err: | 
|  | 3683 | return connectionErrHandler(args.json, "RequestException", err) | 
|  | 3684 |  | 
|  | 3685 | if res.status_code == 403: | 
|  | 3686 | return "The specified thermal control zone(" + args.zone + ")" + \ | 
|  | 3687 | " does not exist" | 
|  | 3688 |  | 
|  | 3689 | return res.text | 
|  | 3690 | else: | 
|  | 3691 | return "Setting thermal control mode(" + args.mode + ")" + \ | 
|  | 3692 | " not supported or operation not available(system powered off?)" | 
|  | 3693 |  | 
|  | 3694 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3695 | def createCommandParser(): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3696 | """ | 
|  | 3697 | creates the parser for the command line along with help for each command and subcommand | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3698 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3699 | @return: returns the parser for the command line | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3700 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3701 | parser = argparse.ArgumentParser(description='Process arguments') | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3702 | parser.add_argument("-H", "--host", help='A hostname or IP for the BMC') | 
|  | 3703 | parser.add_argument("-U", "--user", help='The username to login with') | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3704 | group = parser.add_mutually_exclusive_group() | 
|  | 3705 | group.add_argument("-A", "--askpw", action='store_true', help='prompt for password') | 
|  | 3706 | group.add_argument("-P", "--PW", help='Provide the password in-line') | 
| Joseph Reynolds | a2d54c5 | 2019-06-11 22:02:57 -0500 | [diff] [blame] | 3707 | group.add_argument("-E", "--PWenvvar", action='store_true', help='Get password from envvar OPENBMCTOOL_PASSWORD') | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3708 | parser.add_argument('-j', '--json', action='store_true', help='output json data only') | 
|  | 3709 | parser.add_argument('-t', '--policyTableLoc', help='The location of the policy table to parse alerts') | 
|  | 3710 | parser.add_argument('-c', '--CerFormat', action='store_true', help=argparse.SUPPRESS) | 
|  | 3711 | parser.add_argument('-T', '--procTime', action='store_true', help= argparse.SUPPRESS) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3712 | parser.add_argument('-V', '--version', action='store_true', help='Display the version number of the openbmctool') | 
|  | 3713 | subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command') | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3714 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3715 | #fru command | 
|  | 3716 | parser_inv = subparsers.add_parser("fru", help='Work with platform inventory') | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3717 | inv_subparser = parser_inv.add_subparsers(title='subcommands', description='valid inventory actions', help="valid inventory actions", dest='command') | 
| Justin Thaler | 53bf2f1 | 2018-07-16 14:05:32 -0500 | [diff] [blame] | 3718 | inv_subparser.required = True | 
|  | 3719 | #fru print | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3720 | inv_print = inv_subparser.add_parser("print", help="prints out a list of all FRUs") | 
|  | 3721 | inv_print.set_defaults(func=fruPrint) | 
|  | 3722 | #fru list [0....n] | 
|  | 3723 | inv_list = inv_subparser.add_parser("list", help="print out details on selected FRUs. Specifying no items will list the entire inventory") | 
|  | 3724 | inv_list.add_argument('items', nargs='?', help="print out details on selected FRUs. Specifying no items will list the entire inventory") | 
|  | 3725 | inv_list.set_defaults(func=fruList) | 
|  | 3726 | #fru status | 
|  | 3727 | inv_status = inv_subparser.add_parser("status", help="prints out the status of all FRUs") | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3728 | inv_status.add_argument('-v', '--verbose', action='store_true', help='Verbose output') | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3729 | inv_status.set_defaults(func=fruStatus) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3730 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3731 | #sensors command | 
|  | 3732 | parser_sens = subparsers.add_parser("sensors", help="Work with platform sensors") | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3733 | sens_subparser=parser_sens.add_subparsers(title='subcommands', description='valid sensor actions', help='valid sensor actions', dest='command') | 
| Justin Thaler | 53bf2f1 | 2018-07-16 14:05:32 -0500 | [diff] [blame] | 3734 | sens_subparser.required = True | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3735 | #sensor print | 
|  | 3736 | sens_print= sens_subparser.add_parser('print', help="prints out a list of all Sensors.") | 
|  | 3737 | sens_print.set_defaults(func=sensor) | 
|  | 3738 | #sensor list[0...n] | 
|  | 3739 | sens_list=sens_subparser.add_parser("list", help="Lists all Sensors in the platform. Specify a sensor for full details. ") | 
|  | 3740 | sens_list.add_argument("sensNum", nargs='?', help="The Sensor number to get full details on" ) | 
|  | 3741 | sens_list.set_defaults(func=sensor) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3742 |  | 
| Matthew Barth | 368e83c | 2019-02-01 13:48:25 -0600 | [diff] [blame] | 3743 | #thermal control commands | 
|  | 3744 | parser_therm = subparsers.add_parser("thermal", help="Work with thermal control parameters") | 
|  | 3745 | 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') | 
|  | 3746 | #thermal control zones | 
|  | 3747 | parser_thermZones = therm_subparser.add_parser("zones", help="Get a list of available thermal control zones") | 
|  | 3748 | parser_thermZones.set_defaults(func=getThermalZones) | 
|  | 3749 | #thermal control modes | 
|  | 3750 | parser_thermMode = therm_subparser.add_parser("modes", help="Work with thermal control modes") | 
|  | 3751 | thermMode_sub = parser_thermMode.add_subparsers(title='subactions', description='Work with thermal control modes', help="Work with thermal control modes") | 
|  | 3752 | #get thermal control mode | 
|  | 3753 | parser_getThermMode = thermMode_sub.add_parser("get", help="Get current and supported thermal control modes") | 
|  | 3754 | parser_getThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with') | 
|  | 3755 | parser_getThermMode.set_defaults(func=getThermalMode) | 
|  | 3756 | #set thermal control mode | 
|  | 3757 | parser_setThermMode = thermMode_sub.add_parser("set", help="Set the thermal control mode") | 
|  | 3758 | parser_setThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with') | 
|  | 3759 | parser_setThermMode.add_argument('-m', '--mode', required=True, help='The supported thermal control mode') | 
|  | 3760 | parser_setThermMode.set_defaults(func=setThermalMode) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3761 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3762 | #sel command | 
|  | 3763 | parser_sel = subparsers.add_parser("sel", help="Work with platform alerts") | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3764 | sel_subparser = parser_sel.add_subparsers(title='subcommands', description='valid SEL actions', help = 'valid SEL actions', dest='command') | 
| Justin Thaler | 53bf2f1 | 2018-07-16 14:05:32 -0500 | [diff] [blame] | 3765 | sel_subparser.required = True | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3766 | #sel print | 
|  | 3767 | sel_print = sel_subparser.add_parser("print", help="prints out a list of all sels in a condensed list") | 
|  | 3768 | sel_print.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS) | 
|  | 3769 | sel_print.add_argument('-v', '--verbose', action='store_true', help="Changes the output to being very verbose") | 
|  | 3770 | sel_print.add_argument('-f', '--fileloc', help='Parse a file instead of the BMC output') | 
|  | 3771 | sel_print.set_defaults(func=selPrint) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3772 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3773 | #sel list | 
|  | 3774 | 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") | 
|  | 3775 | sel_list.add_argument("selNum", nargs='?', type=int, help="The SEL entry to get details on") | 
|  | 3776 | sel_list.set_defaults(func=selList) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3777 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3778 | sel_get = sel_subparser.add_parser("get", help="Gets the verbose details of a specified SEL entry") | 
|  | 3779 | sel_get.add_argument('selNum', type=int, help="the number of the SEL entry to get") | 
|  | 3780 | sel_get.set_defaults(func=selList) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3781 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3782 | sel_clear = sel_subparser.add_parser("clear", help="Clears all entries from the SEL") | 
|  | 3783 | sel_clear.set_defaults(func=selClear) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3784 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3785 | sel_setResolved = sel_subparser.add_parser("resolve", help="Sets the sel entry to resolved") | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3786 | sel_setResolved.add_argument('-n', '--selNum', type=int, help="the number of the SEL entry to resolve") | 
|  | 3787 | sel_ResolveAll_sub = sel_setResolved.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command') | 
|  | 3788 | sel_ResolveAll = sel_ResolveAll_sub.add_parser('all', help='Resolve all SEL entries') | 
|  | 3789 | sel_ResolveAll.set_defaults(func=selResolveAll) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3790 | sel_setResolved.set_defaults(func=selSetResolved) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3791 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3792 | parser_chassis = subparsers.add_parser("chassis", help="Work with chassis power and status") | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3793 | chas_sub = parser_chassis.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command') | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3794 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3795 | parser_chassis.add_argument('status', action='store_true', help='Returns the current status of the platform') | 
|  | 3796 | parser_chassis.set_defaults(func=chassis) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3797 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3798 | parser_chasPower = chas_sub.add_parser("power", help="Turn the chassis on or off, check the power state") | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3799 | parser_chasPower.add_argument('powcmd',  choices=['on','softoff', 'hardoff', 'status'], help='The value for the power command. on, off, or status') | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3800 | parser_chasPower.set_defaults(func=chassisPower) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3801 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3802 | #control the chassis identify led | 
|  | 3803 | parser_chasIdent = chas_sub.add_parser("identify", help="Control the chassis identify led") | 
|  | 3804 | parser_chasIdent.add_argument('identcmd', choices=['on', 'off', 'status'], help='The control option for the led: on, off, blink, status') | 
|  | 3805 | parser_chasIdent.set_defaults(func=chassisIdent) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3806 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3807 | #collect service data | 
|  | 3808 | parser_servData = subparsers.add_parser("collect_service_data", help="Collect all bmc data needed for service") | 
|  | 3809 | parser_servData.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS) | 
|  | 3810 | parser_servData.set_defaults(func=collectServiceData) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3811 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3812 | #system quick health check | 
|  | 3813 | parser_healthChk = subparsers.add_parser("health_check", help="Work with platform sensors") | 
|  | 3814 | parser_healthChk.set_defaults(func=healthCheck) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3815 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3816 | #work with bmc dumps | 
|  | 3817 | parser_bmcdump = subparsers.add_parser("dump", help="Work with bmc dump files") | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3818 | bmcDump_sub = parser_bmcdump.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command') | 
| Justin Thaler | 53bf2f1 | 2018-07-16 14:05:32 -0500 | [diff] [blame] | 3819 | bmcDump_sub.required = True | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3820 | dump_Create = bmcDump_sub.add_parser('create', help="Create a bmc dump") | 
|  | 3821 | dump_Create.set_defaults(func=bmcDumpCreate) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3822 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3823 | dump_list = bmcDump_sub.add_parser('list', help="list all bmc dump files") | 
|  | 3824 | dump_list.set_defaults(func=bmcDumpList) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3825 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3826 | parserdumpdelete = bmcDump_sub.add_parser('delete', help="Delete bmc dump files") | 
|  | 3827 | parserdumpdelete.add_argument("-n", "--dumpNum", nargs='*', type=int, help="The Dump entry to delete") | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3828 | parserdumpdelete.set_defaults(func=bmcDumpDelete) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3829 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3830 | bmcDumpDelsub = parserdumpdelete.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command') | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3831 | deleteAllDumps = bmcDumpDelsub.add_parser('all', help='Delete all bmc dump files') | 
|  | 3832 | deleteAllDumps.set_defaults(func=bmcDumpDeleteAll) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3833 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3834 | parser_dumpretrieve = bmcDump_sub.add_parser('retrieve', help='Retrieve a dump file') | 
|  | 3835 | parser_dumpretrieve.add_argument("dumpNum", type=int, help="The Dump entry to delete") | 
|  | 3836 | parser_dumpretrieve.add_argument("-s", "--dumpSaveLoc", help="The location to save the bmc dump file") | 
|  | 3837 | parser_dumpretrieve.set_defaults(func=bmcDumpRetrieve) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3838 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 3839 | #bmc command for reseting the bmc | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3840 | parser_bmc = subparsers.add_parser('bmc', help="Work with the bmc") | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3841 | bmc_sub = parser_bmc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command') | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3842 | parser_BMCReset = bmc_sub.add_parser('reset', help='Reset the bmc' ) | 
|  | 3843 | parser_BMCReset.add_argument('type', choices=['warm','cold'], help="Warm: Reboot the BMC, Cold: CLEAR config and reboot bmc") | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3844 | 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.") | 
|  | 3845 | parser_bmc.set_defaults(func=bmc) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3846 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3847 | #add alias to the bmc command | 
|  | 3848 | parser_mc = subparsers.add_parser('mc', help="Work with the management controller") | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3849 | mc_sub = parser_mc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command') | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3850 | parser_MCReset = mc_sub.add_parser('reset', help='Reset the bmc' ) | 
|  | 3851 | parser_MCReset.add_argument('type', choices=['warm','cold'], help="Reboot the BMC") | 
|  | 3852 | #parser_MCReset.add_argument('cold', action='store_true', help="Reboot the BMC and CLEAR the configuration") | 
|  | 3853 | 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 Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3854 | parser_MCReset.set_defaults(func=bmcReset) | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 3855 | parser_mc.set_defaults(func=bmc) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3856 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3857 | #gard clear | 
|  | 3858 | parser_gc = subparsers.add_parser("gardclear", help="Used to clear gard records") | 
|  | 3859 | parser_gc.set_defaults(func=gardClear) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3860 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3861 | #firmware_flash | 
|  | 3862 | parser_fw = subparsers.add_parser("firmware", help="Work with the system firmware") | 
|  | 3863 | fwflash_subproc = parser_fw.add_subparsers(title='subcommands', description='valid firmware commands', help='sub-command help', dest='command') | 
| Justin Thaler | 53bf2f1 | 2018-07-16 14:05:32 -0500 | [diff] [blame] | 3864 | fwflash_subproc.required = True | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3865 |  | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3866 | fwflash = fwflash_subproc.add_parser('flash', help="Flash the system firmware") | 
|  | 3867 | fwflash.add_argument('type', choices=['bmc', 'pnor'], help="image type to flash") | 
|  | 3868 | fwflash.add_argument('-f', '--fileloc', required=True, help="The absolute path to the firmware image") | 
|  | 3869 | fwflash.set_defaults(func=fwFlash) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3870 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 3871 | fwActivate = fwflash_subproc.add_parser('activate', help="Activate existing image on the bmc") | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 3872 | fwActivate.add_argument('imageID', help="The image ID to activate from the firmware list. Ex: 63c95399") | 
|  | 3873 | fwActivate.set_defaults(func=activateFWImage) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3874 |  | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 3875 | fwActivateStatus = fwflash_subproc.add_parser('activation_status', help="Check Status of activations") | 
|  | 3876 | fwActivateStatus.set_defaults(func=activateStatus) | 
|  | 3877 |  | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 3878 | fwList = fwflash_subproc.add_parser('list', help="List all of the installed firmware") | 
|  | 3879 | fwList.add_argument('-v', '--verbose', action='store_true', help='Verbose output') | 
|  | 3880 | fwList.set_defaults(func=firmwareList) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3881 |  | 
| Justin Thaler | 3d71d40 | 2018-07-24 14:35:39 -0500 | [diff] [blame] | 3882 | fwprint = fwflash_subproc.add_parser('print', help="List all of the installed firmware") | 
|  | 3883 | fwprint.add_argument('-v', '--verbose', action='store_true', help='Verbose output') | 
|  | 3884 | fwprint.set_defaults(func=firmwareList) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3885 |  | 
| Adriana Kobylak | 5af2fad | 2018-11-08 12:33:43 -0600 | [diff] [blame] | 3886 | fwDelete = fwflash_subproc.add_parser('delete', help="Delete an existing firmware version") | 
|  | 3887 | fwDelete.add_argument('versionID', help="The version ID to delete from the firmware list. Ex: 63c95399") | 
|  | 3888 | fwDelete.set_defaults(func=deleteFWVersion) | 
|  | 3889 |  | 
| Deepak Kodihalli | 22d4df0 | 2018-09-18 06:52:43 -0500 | [diff] [blame] | 3890 | #logging | 
|  | 3891 | parser_logging = subparsers.add_parser("logging", help="logging controls") | 
|  | 3892 | logging_sub = parser_logging.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command') | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3893 |  | 
| Deepak Kodihalli | 22d4df0 | 2018-09-18 06:52:43 -0500 | [diff] [blame] | 3894 | #turn rest api logging on/off | 
|  | 3895 | parser_rest_logging = logging_sub.add_parser("rest_api", help="turn rest api logging on/off") | 
|  | 3896 | parser_rest_logging.add_argument('rest_logging', choices=['on', 'off'], help='The control option for rest logging: on, off') | 
|  | 3897 | parser_rest_logging.set_defaults(func=restLogging) | 
| Deepak Kodihalli | 02d5328 | 2018-09-18 06:53:31 -0500 | [diff] [blame] | 3898 |  | 
|  | 3899 | #remote logging | 
|  | 3900 | parser_remote_logging = logging_sub.add_parser("remote_logging", help="Remote logging (rsyslog) commands") | 
|  | 3901 | parser_remote_logging.add_argument('remote_logging', choices=['view', 'disable'], help='Remote logging (rsyslog) commands') | 
|  | 3902 | parser_remote_logging.set_defaults(func=remoteLogging) | 
|  | 3903 |  | 
|  | 3904 | #configure remote logging | 
|  | 3905 | parser_remote_logging_config = logging_sub.add_parser("remote_logging_config", help="Configure remote logging (rsyslog)") | 
|  | 3906 | parser_remote_logging_config.add_argument("-a", "--address", required=True, help="Set IP address of rsyslog server") | 
|  | 3907 | parser_remote_logging_config.add_argument("-p", "--port", required=True, type=int, help="Set Port of rsyslog server") | 
|  | 3908 | parser_remote_logging_config.set_defaults(func=remoteLoggingConfig) | 
| Dhruvaraj Subhashchandran | 64e7f6f | 2018-10-02 03:42:14 -0500 | [diff] [blame] | 3909 |  | 
|  | 3910 | #certificate management | 
|  | 3911 | parser_cert = subparsers.add_parser("certificate", help="Certificate management") | 
|  | 3912 | certMgmt_subproc = parser_cert.add_subparsers(title='subcommands', description='valid certificate commands', help='sub-command help', dest='command') | 
|  | 3913 |  | 
|  | 3914 | certUpdate = certMgmt_subproc.add_parser('update', help="Update the certificate") | 
|  | 3915 | certUpdate.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to update") | 
|  | 3916 | certUpdate.add_argument('service', choices=['https', 'ldap'], help="Service to update") | 
|  | 3917 | certUpdate.add_argument('-f', '--fileloc', required=True, help="The absolute path to the certificate file") | 
|  | 3918 | certUpdate.set_defaults(func=certificateUpdate) | 
|  | 3919 |  | 
|  | 3920 | certDelete = certMgmt_subproc.add_parser('delete', help="Delete the certificate") | 
|  | 3921 | certDelete.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to delete") | 
|  | 3922 | certDelete.add_argument('service', choices=['https', 'ldap'], help="Service to delete the certificate") | 
|  | 3923 | certDelete.set_defaults(func=certificateDelete) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 3924 |  | 
| Matt Spinler | 7d426c2 | 2018-09-24 14:42:07 -0500 | [diff] [blame] | 3925 | # local users | 
|  | 3926 | parser_users = subparsers.add_parser("local_users", help="Work with local users") | 
|  | 3927 | parser_users.add_argument('local_users', choices=['disableall','enableall', 'queryenabled'], help="Disable, enable or query local user accounts") | 
|  | 3928 | parser_users.add_argument('-v', '--verbose', action='store_true', help='Verbose output') | 
|  | 3929 | parser_users.set_defaults(func=localUsers) | 
|  | 3930 |  | 
| Ratan Gupta | 9166cd2 | 2018-10-01 18:09:40 +0530 | [diff] [blame] | 3931 | #LDAP | 
|  | 3932 | parser_ldap = subparsers.add_parser("ldap", help="LDAP controls") | 
|  | 3933 | ldap_sub = parser_ldap.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command') | 
|  | 3934 |  | 
|  | 3935 | #configure and enable LDAP | 
|  | 3936 | parser_ldap_config = ldap_sub.add_parser("enable", help="Configure and enables the LDAP") | 
|  | 3937 | parser_ldap_config.add_argument("-a", "--uri", required=True, help="Set LDAP server URI") | 
|  | 3938 | parser_ldap_config.add_argument("-B", "--bindDN", required=True, help="Set the bind DN of the LDAP server") | 
|  | 3939 | parser_ldap_config.add_argument("-b", "--baseDN", required=True, help="Set the base DN of the LDAP server") | 
|  | 3940 | parser_ldap_config.add_argument("-p", "--bindPassword", required=True, help="Set the bind password of the LDAP server") | 
|  | 3941 | parser_ldap_config.add_argument("-S", "--scope", choices=['sub','one', 'base'], | 
|  | 3942 | help='Specifies the search scope:subtree, one level or base object.') | 
|  | 3943 | parser_ldap_config.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'], | 
|  | 3944 | help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap') | 
|  | 3945 | parser_ldap_config.set_defaults(func=enableLDAP) | 
|  | 3946 |  | 
|  | 3947 | # disable LDAP | 
|  | 3948 | parser_disable_ldap = ldap_sub.add_parser("disable", help="disables the LDAP") | 
|  | 3949 | parser_disable_ldap.set_defaults(func=disableLDAP) | 
| Nagaraju Goruganti | 7d1fe17 | 2018-11-13 06:09:29 -0600 | [diff] [blame] | 3950 | # view-config | 
|  | 3951 | parser_ldap_config = \ | 
|  | 3952 | ldap_sub.add_parser("view-config", help="prints out a list of all \ | 
|  | 3953 | LDAPS's configured properties") | 
|  | 3954 | parser_ldap_config.set_defaults(func=viewLDAPConfig) | 
| Ratan Gupta | 9166cd2 | 2018-10-01 18:09:40 +0530 | [diff] [blame] | 3955 |  | 
| Ratan Gupta | feee637 | 2018-10-17 23:25:51 +0530 | [diff] [blame] | 3956 | #create group privilege mapping | 
|  | 3957 | parser_ldap_mapper = ldap_sub.add_parser("privilege-mapper", help="LDAP group privilege controls") | 
|  | 3958 | parser_ldap_mapper_sub = parser_ldap_mapper.add_subparsers(title='subcommands', description='valid subcommands', | 
|  | 3959 | help="sub-command help", dest='command') | 
|  | 3960 |  | 
|  | 3961 | parser_ldap_mapper_create = parser_ldap_mapper_sub.add_parser("create", help="Create mapping of ldap group and privilege") | 
|  | 3962 | parser_ldap_mapper_create.add_argument("-g","--groupName",required=True,help="Group Name") | 
|  | 3963 | parser_ldap_mapper_create.add_argument("-p","--privilege",choices=['priv-admin','priv-user'],required=True,help="Privilege") | 
|  | 3964 | parser_ldap_mapper_create.set_defaults(func=createPrivilegeMapping) | 
|  | 3965 |  | 
|  | 3966 | #list group privilege mapping | 
|  | 3967 | parser_ldap_mapper_list = parser_ldap_mapper_sub.add_parser("list",help="List privilege mapping") | 
|  | 3968 | parser_ldap_mapper_list.set_defaults(func=listPrivilegeMapping) | 
|  | 3969 |  | 
|  | 3970 | #delete group privilege mapping | 
|  | 3971 | parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("delete",help="Delete privilege mapping") | 
|  | 3972 | parser_ldap_mapper_delete.add_argument("-g","--groupName",required=True,help="Group Name") | 
|  | 3973 | parser_ldap_mapper_delete.set_defaults(func=deletePrivilegeMapping) | 
|  | 3974 |  | 
| Sivas SRR | 7883527 | 2018-11-27 05:27:19 -0600 | [diff] [blame] | 3975 | #deleteAll group privilege mapping | 
|  | 3976 | parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("purge",help="Delete All privilege mapping") | 
|  | 3977 | parser_ldap_mapper_delete.set_defaults(func=deleteAllPrivilegeMapping) | 
|  | 3978 |  | 
| Marri Devender Rao | 2c2a516 | 2018-11-05 08:57:11 -0600 | [diff] [blame] | 3979 | # set local user password | 
|  | 3980 | parser_set_password = subparsers.add_parser("set_password", | 
|  | 3981 | help="Set password of local user") | 
|  | 3982 | parser_set_password.add_argument( "-p", "--password", required=True, | 
|  | 3983 | help="Password of local user") | 
|  | 3984 | parser_set_password.set_defaults(func=setPassword) | 
|  | 3985 |  | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 3986 | # network | 
|  | 3987 | parser_nw = subparsers.add_parser("network", help="network controls") | 
|  | 3988 | nw_sub = parser_nw.add_subparsers(title='subcommands', | 
|  | 3989 | description='valid subcommands', | 
|  | 3990 | help="sub-command help", | 
|  | 3991 | dest='command') | 
|  | 3992 |  | 
|  | 3993 | # enable DHCP | 
|  | 3994 | parser_enable_dhcp = nw_sub.add_parser("enableDHCP", | 
|  | 3995 | help="enables the DHCP on given " | 
|  | 3996 | "Interface") | 
|  | 3997 | parser_enable_dhcp.add_argument("-I", "--Interface", required=True, | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 3998 | help="Name of the ethernet interface(it can" | 
|  | 3999 | "be obtained by the " | 
|  | 4000 | "command:network view-config)" | 
|  | 4001 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 4002 | parser_enable_dhcp.set_defaults(func=enableDHCP) | 
|  | 4003 |  | 
|  | 4004 | # disable DHCP | 
|  | 4005 | parser_disable_dhcp = nw_sub.add_parser("disableDHCP", | 
|  | 4006 | help="disables the DHCP on given " | 
|  | 4007 | "Interface") | 
|  | 4008 | parser_disable_dhcp.add_argument("-I", "--Interface", required=True, | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 4009 | help="Name of the ethernet interface(it can" | 
|  | 4010 | "be obtained by the " | 
|  | 4011 | "command:network view-config)" | 
|  | 4012 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 4013 | parser_disable_dhcp.set_defaults(func=disableDHCP) | 
|  | 4014 |  | 
|  | 4015 | # get HostName | 
|  | 4016 | parser_gethostname = nw_sub.add_parser("getHostName", | 
|  | 4017 | help="prints out HostName") | 
|  | 4018 | parser_gethostname.set_defaults(func=getHostname) | 
|  | 4019 |  | 
|  | 4020 | # set HostName | 
|  | 4021 | parser_sethostname = nw_sub.add_parser("setHostName", help="sets HostName") | 
|  | 4022 | parser_sethostname.add_argument("-H", "--HostName", required=True, | 
|  | 4023 | help="A HostName for the BMC") | 
|  | 4024 | parser_sethostname.set_defaults(func=setHostname) | 
|  | 4025 |  | 
|  | 4026 | # get domainname | 
|  | 4027 | parser_getdomainname = nw_sub.add_parser("getDomainName", | 
|  | 4028 | help="prints out DomainName of " | 
|  | 4029 | "given Interface") | 
|  | 4030 | parser_getdomainname.add_argument("-I", "--Interface", required=True, | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 4031 | help="Name of the ethernet interface(it " | 
|  | 4032 | "can be obtained by the " | 
|  | 4033 | "command:network view-config)" | 
|  | 4034 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 4035 | parser_getdomainname.set_defaults(func=getDomainName) | 
|  | 4036 |  | 
|  | 4037 | # set domainname | 
|  | 4038 | parser_setdomainname = nw_sub.add_parser("setDomainName", | 
|  | 4039 | help="sets DomainName of given " | 
|  | 4040 | "Interface") | 
|  | 4041 | parser_setdomainname.add_argument("-D", "--DomainName", required=True, | 
|  | 4042 | help="Ex: DomainName=Domain1,Domain2,...") | 
|  | 4043 | parser_setdomainname.add_argument("-I", "--Interface", required=True, | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 4044 | help="Name of the ethernet interface(it " | 
|  | 4045 | "can be obtained by the " | 
|  | 4046 | "command:network view-config)" | 
|  | 4047 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 4048 | parser_setdomainname.set_defaults(func=setDomainName) | 
|  | 4049 |  | 
|  | 4050 | # get MACAddress | 
|  | 4051 | parser_getmacaddress = nw_sub.add_parser("getMACAddress", | 
|  | 4052 | help="prints out MACAddress the " | 
|  | 4053 | "given Interface") | 
|  | 4054 | parser_getmacaddress.add_argument("-I", "--Interface", required=True, | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 4055 | help="Name of the ethernet interface(it " | 
|  | 4056 | "can be obtained by the " | 
|  | 4057 | "command:network view-config)" | 
|  | 4058 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 4059 | parser_getmacaddress.set_defaults(func=getMACAddress) | 
|  | 4060 |  | 
|  | 4061 | # set MACAddress | 
|  | 4062 | parser_setmacaddress = nw_sub.add_parser("setMACAddress", | 
|  | 4063 | help="sets MACAddress") | 
|  | 4064 | parser_setmacaddress.add_argument("-MA", "--MACAddress", required=True, | 
|  | 4065 | help="A MACAddress for the given " | 
|  | 4066 | "Interface") | 
|  | 4067 | parser_setmacaddress.add_argument("-I", "--Interface", required=True, | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 4068 | help="Name of the ethernet interface(it can" | 
|  | 4069 | "be obtained by the " | 
|  | 4070 | "command:network view-config)" | 
|  | 4071 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 4072 | parser_setmacaddress.set_defaults(func=setMACAddress) | 
|  | 4073 |  | 
|  | 4074 | # get DefaultGW | 
|  | 4075 | parser_getdefaultgw = nw_sub.add_parser("getDefaultGW", | 
|  | 4076 | help="prints out DefaultGateway " | 
|  | 4077 | "the BMC") | 
|  | 4078 | parser_getdefaultgw.set_defaults(func=getDefaultGateway) | 
|  | 4079 |  | 
|  | 4080 | # set DefaultGW | 
|  | 4081 | parser_setdefaultgw = nw_sub.add_parser("setDefaultGW", | 
|  | 4082 | help="sets DefaultGW") | 
|  | 4083 | parser_setdefaultgw.add_argument("-GW", "--DefaultGW", required=True, | 
|  | 4084 | help="A DefaultGateway for the BMC") | 
|  | 4085 | parser_setdefaultgw.set_defaults(func=setDefaultGateway) | 
|  | 4086 |  | 
|  | 4087 | # view network Config | 
|  | 4088 | parser_ldap_config = nw_sub.add_parser("view-config", help="prints out a " | 
|  | 4089 | "list of all network's configured " | 
|  | 4090 | "properties") | 
|  | 4091 | parser_ldap_config.set_defaults(func=viewNWConfig) | 
|  | 4092 |  | 
|  | 4093 | # get DNS | 
|  | 4094 | parser_getDNS = nw_sub.add_parser("getDNS", | 
|  | 4095 | help="prints out DNS servers on the " | 
|  | 4096 | "given interface") | 
|  | 4097 | parser_getDNS.add_argument("-I", "--Interface", required=True, | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 4098 | help="Name of the ethernet interface(it can" | 
|  | 4099 | "be obtained by the " | 
|  | 4100 | "command:network view-config)" | 
|  | 4101 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 4102 | parser_getDNS.set_defaults(func=getDNS) | 
|  | 4103 |  | 
|  | 4104 | # set DNS | 
|  | 4105 | parser_setDNS = nw_sub.add_parser("setDNS", | 
|  | 4106 | help="sets DNS servers on the given " | 
|  | 4107 | "interface") | 
|  | 4108 | parser_setDNS.add_argument("-d", "--DNSServers", required=True, | 
|  | 4109 | help="Ex: DNSSERVERS=DNS1,DNS2,...") | 
|  | 4110 | parser_setDNS.add_argument("-I", "--Interface", required=True, | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 4111 | help="Name of the ethernet interface(it can" | 
|  | 4112 | "be obtained by the " | 
|  | 4113 | "command:network view-config)" | 
|  | 4114 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 4115 | parser_setDNS.set_defaults(func=setDNS) | 
|  | 4116 |  | 
|  | 4117 | # get NTP | 
|  | 4118 | parser_getNTP = nw_sub.add_parser("getNTP", | 
|  | 4119 | help="prints out NTP servers on the " | 
|  | 4120 | "given interface") | 
|  | 4121 | parser_getNTP.add_argument("-I", "--Interface", required=True, | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 4122 | help="Name of the ethernet interface(it can" | 
|  | 4123 | "be obtained by the " | 
|  | 4124 | "command:network view-config)" | 
|  | 4125 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 4126 | parser_getNTP.set_defaults(func=getNTP) | 
|  | 4127 |  | 
|  | 4128 | # set NTP | 
|  | 4129 | parser_setNTP = nw_sub.add_parser("setNTP", | 
|  | 4130 | help="sets NTP servers on the given " | 
|  | 4131 | "interface") | 
|  | 4132 | parser_setNTP.add_argument("-N", "--NTPServers", required=True, | 
|  | 4133 | help="Ex: NTPSERVERS=NTP1,NTP2,...") | 
|  | 4134 | parser_setNTP.add_argument("-I", "--Interface", required=True, | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 4135 | help="Name of the ethernet interface(it can" | 
|  | 4136 | "be obtained by the " | 
|  | 4137 | "command:network view-config)" | 
|  | 4138 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
| Nagaraju Goruganti | 9908bcf | 2018-11-14 22:07:25 -0600 | [diff] [blame] | 4139 | parser_setNTP.set_defaults(func=setNTP) | 
|  | 4140 |  | 
| Nagaraju Goruganti | 97a2060 | 2018-11-16 03:06:08 -0600 | [diff] [blame] | 4141 | # configure IP | 
|  | 4142 | parser_ip_config = nw_sub.add_parser("addIP", help="Sets IP address to" | 
|  | 4143 | "given interface") | 
|  | 4144 | parser_ip_config.add_argument("-a", "--address", required=True, | 
|  | 4145 | help="IP address of given interface") | 
|  | 4146 | parser_ip_config.add_argument("-gw", "--gateway", required=False, default='', | 
|  | 4147 | help="The gateway for given interface") | 
|  | 4148 | parser_ip_config.add_argument("-l", "--prefixLength", required=True, | 
|  | 4149 | help="The prefixLength of IP address") | 
|  | 4150 | parser_ip_config.add_argument("-p", "--type", choices=['ipv4', 'ipv6'], | 
|  | 4151 | help="The protocol type of the given" | 
|  | 4152 | "IP address") | 
|  | 4153 | parser_ip_config.add_argument("-I", "--Interface", required=True, | 
|  | 4154 | help="Name of the ethernet interface(it can" | 
|  | 4155 | "be obtained by the " | 
|  | 4156 | "command:network view-config)" | 
|  | 4157 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
|  | 4158 | parser_ip_config.set_defaults(func=addIP) | 
|  | 4159 |  | 
|  | 4160 | # getIP | 
|  | 4161 | parser_getIP = nw_sub.add_parser("getIP", help="prints out IP address" | 
|  | 4162 | "of given interface") | 
|  | 4163 | parser_getIP.add_argument("-I", "--Interface", required=True, | 
|  | 4164 | help="Name of the ethernet interface(it can" | 
|  | 4165 | "be obtained by the command:network view-config)" | 
|  | 4166 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
|  | 4167 | parser_getIP.set_defaults(func=getIP) | 
|  | 4168 |  | 
|  | 4169 | # rmIP | 
|  | 4170 | parser_rmIP = nw_sub.add_parser("rmIP", help="deletes IP address" | 
|  | 4171 | "of given interface") | 
|  | 4172 | parser_rmIP.add_argument("-a", "--address", required=True, | 
|  | 4173 | help="IP address to remove form given Interface") | 
|  | 4174 | parser_rmIP.add_argument("-I", "--Interface", required=True, | 
|  | 4175 | help="Name of the ethernet interface(it can" | 
|  | 4176 | "be obtained by the command:network view-config)" | 
|  | 4177 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
|  | 4178 | parser_rmIP.set_defaults(func=deleteIP) | 
|  | 4179 |  | 
| Nagaraju Goruganti | f21d43c | 2018-11-19 10:47:19 -0600 | [diff] [blame] | 4180 | # add VLAN | 
|  | 4181 | parser_create_vlan = nw_sub.add_parser("addVLAN", help="enables VLAN " | 
|  | 4182 | "on given interface with given " | 
|  | 4183 | "VLAN Identifier") | 
|  | 4184 | parser_create_vlan.add_argument("-I", "--Interface", required=True, | 
|  | 4185 | choices=['eth0', 'eth1'], | 
|  | 4186 | help="Name of the ethernet interface") | 
|  | 4187 | parser_create_vlan.add_argument("-n", "--Identifier", required=True, | 
|  | 4188 | help="VLAN Identifier") | 
|  | 4189 | parser_create_vlan.set_defaults(func=addVLAN) | 
|  | 4190 |  | 
|  | 4191 | # delete VLAN | 
|  | 4192 | parser_delete_vlan = nw_sub.add_parser("deleteVLAN", help="disables VLAN " | 
|  | 4193 | "on given interface with given " | 
|  | 4194 | "VLAN Identifier") | 
|  | 4195 | parser_delete_vlan.add_argument("-I", "--Interface", required=True, | 
|  | 4196 | help="Name of the ethernet interface(it can" | 
|  | 4197 | "be obtained by the " | 
|  | 4198 | "command:network view-config)" | 
|  | 4199 | "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)") | 
|  | 4200 | parser_delete_vlan.set_defaults(func=deleteVLAN) | 
|  | 4201 |  | 
|  | 4202 | # viewDHCPConfig | 
|  | 4203 | parser_viewDHCPConfig = nw_sub.add_parser("viewDHCPConfig", | 
|  | 4204 | help="Shows DHCP configured " | 
|  | 4205 | "Properties") | 
|  | 4206 | parser_viewDHCPConfig.set_defaults(func=viewDHCPConfig) | 
|  | 4207 |  | 
|  | 4208 | # configureDHCP | 
|  | 4209 | parser_configDHCP = nw_sub.add_parser("configureDHCP", | 
|  | 4210 | help="Configures/updates DHCP " | 
|  | 4211 | "Properties") | 
|  | 4212 | parser_configDHCP.add_argument("-d", "--DNSEnabled", type=str2bool, | 
|  | 4213 | required=True, help="Sets DNSEnabled property") | 
|  | 4214 | parser_configDHCP.add_argument("-n", "--HostNameEnabled", type=str2bool, | 
|  | 4215 | required=True, | 
|  | 4216 | help="Sets HostNameEnabled property") | 
|  | 4217 | parser_configDHCP.add_argument("-t", "--NTPEnabled", type=str2bool, | 
|  | 4218 | required=True, | 
|  | 4219 | help="Sets NTPEnabled property") | 
|  | 4220 | parser_configDHCP.add_argument("-s", "--SendHostNameEnabled", type=str2bool, | 
|  | 4221 | required=True, | 
|  | 4222 | help="Sets SendHostNameEnabled property") | 
|  | 4223 | parser_configDHCP.set_defaults(func=configureDHCP) | 
|  | 4224 |  | 
|  | 4225 | # network factory reset | 
|  | 4226 | parser_nw_reset = nw_sub.add_parser("nwReset", | 
|  | 4227 | help="Resets networks setting to " | 
|  | 4228 | "factory defaults. " | 
|  | 4229 | "note:Reset settings will be applied " | 
|  | 4230 | "after BMC reboot") | 
|  | 4231 | parser_nw_reset.set_defaults(func=nwReset) | 
|  | 4232 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 4233 | return parser | 
|  | 4234 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 4235 | def main(argv=None): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 4236 | """ | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 4237 | main function for running the command line utility as a sub application | 
|  | 4238 | """ | 
|  | 4239 | global toolVersion | 
| Marri Devender Rao | 82590dc | 2019-06-06 04:54:22 -0500 | [diff] [blame^] | 4240 | toolVersion = "1.15" | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 4241 | parser = createCommandParser() | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 4242 | args = parser.parse_args(argv) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 4243 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 4244 | totTimeStart = int(round(time.time()*1000)) | 
|  | 4245 |  | 
|  | 4246 | if(sys.version_info < (3,0)): | 
|  | 4247 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) | 
|  | 4248 | if sys.version_info >= (3,0): | 
|  | 4249 | requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 4250 | if (args.version): | 
| Justin Thaler | 22b1bb5 | 2018-03-15 13:31:32 -0500 | [diff] [blame] | 4251 | print("Version: "+ toolVersion) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 4252 | sys.exit(0) | 
|  | 4253 | if (hasattr(args, 'fileloc') and args.fileloc is not None and 'print' in args.command): | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 4254 | mysess = None | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 4255 | print(selPrint('N/A', args, mysess)) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 4256 | else: | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 4257 | if(hasattr(args, 'host') and hasattr(args,'user')): | 
|  | 4258 | if (args.askpw): | 
|  | 4259 | pw = getpass.getpass() | 
|  | 4260 | elif(args.PW is not None): | 
|  | 4261 | pw = args.PW | 
| Joseph Reynolds | a2d54c5 | 2019-06-11 22:02:57 -0500 | [diff] [blame] | 4262 | elif(args.PWenvvar): | 
|  | 4263 | pw = os.environ['OPENBMCTOOL_PASSWORD'] | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 4264 | else: | 
|  | 4265 | print("You must specify a password") | 
|  | 4266 | sys.exit() | 
|  | 4267 | logintimeStart = int(round(time.time()*1000)) | 
|  | 4268 | mysess = login(args.host, args.user, pw, args.json) | 
| Justin Thaler | a9415b4 | 2018-05-25 19:40:13 -0500 | [diff] [blame] | 4269 | if(sys.version_info < (3,0)): | 
|  | 4270 | if isinstance(mysess, basestring): | 
|  | 4271 | print(mysess) | 
|  | 4272 | sys.exit(1) | 
|  | 4273 | elif sys.version_info >= (3,0): | 
|  | 4274 | if isinstance(mysess, str): | 
|  | 4275 | print(mysess) | 
|  | 4276 | sys.exit(1) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 4277 | logintimeStop = int(round(time.time()*1000)) | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 4278 |  | 
|  | 4279 | commandTimeStart = int(round(time.time()*1000)) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 4280 | output = args.func(args.host, args, mysess) | 
|  | 4281 | commandTimeStop = int(round(time.time()*1000)) | 
| Justin Thaler | 761484a | 2019-03-26 19:20:23 -0500 | [diff] [blame] | 4282 | if isinstance(output, dict): | 
|  | 4283 | print(json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)) | 
|  | 4284 | else: | 
|  | 4285 | print(output) | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 4286 | if (mysess is not None): | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 4287 | logout(args.host, args.user, pw, mysess, args.json) | 
|  | 4288 | if(args.procTime): | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 4289 | print("Total time: " + str(int(round(time.time()*1000))- totTimeStart)) | 
|  | 4290 | print("loginTime: " + str(logintimeStop - logintimeStart)) | 
|  | 4291 | print("command Time: " + str(commandTimeStop - commandTimeStart)) | 
|  | 4292 | else: | 
| Joseph Reynolds | a2d54c5 | 2019-06-11 22:02:57 -0500 | [diff] [blame] | 4293 | print("usage:\n" | 
|  | 4294 | "  OPENBMCTOOL_PASSWORD=secret  # if using -E\n" | 
|  | 4295 | "  openbmctool.py [-h] -H HOST -U USER {-A | -P PW | -E} [-j]\n" + | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 4296 | "\t[-t POLICYTABLELOC] [-V]\n" + | 
| Deepak Kodihalli | 22d4df0 | 2018-09-18 06:52:43 -0500 | [diff] [blame] | 4297 | "\t{fru,sensors,sel,chassis,collect_service_data, \ | 
|  | 4298 | health_check,dump,bmc,mc,gardclear,firmware,logging}\n" + | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 4299 | "\t...\n" + | 
|  | 4300 | "openbmctool.py: error: the following arguments are required: -H/--host, -U/--user") | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 4301 | sys.exit() | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 4302 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 4303 | if __name__ == '__main__': | 
| Justin Thaler | e412dc2 | 2018-01-12 16:28:24 -0600 | [diff] [blame] | 4304 | """ | 
|  | 4305 | main function when called from the command line | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 4306 |  | 
|  | 4307 | """ | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 4308 | import sys | 
| Nagaraju Goruganti | c1a00af | 2018-11-07 00:52:11 -0600 | [diff] [blame] | 4309 |  | 
| Justin Thaler | f9aee3e | 2017-12-05 12:11:09 -0600 | [diff] [blame] | 4310 | isTTY = sys.stdout.isatty() | 
|  | 4311 | assert sys.version_info >= (2,7) | 
|  | 4312 | main() |