169419bafSAndrew Jeffery#!/usr/bin/python3
269419bafSAndrew Jeffery"""
369419bafSAndrew Jeffery Copyright 2017,2019 IBM Corporation
469419bafSAndrew Jeffery
569419bafSAndrew Jeffery   Licensed under the Apache License, Version 2.0 (the "License");
669419bafSAndrew Jeffery   you may not use this file except in compliance with the License.
769419bafSAndrew Jeffery   You may obtain a copy of the License at
869419bafSAndrew Jeffery
969419bafSAndrew Jeffery       http://www.apache.org/licenses/LICENSE-2.0
1069419bafSAndrew Jeffery
1169419bafSAndrew Jeffery   Unless required by applicable law or agreed to in writing, software
1269419bafSAndrew Jeffery   distributed under the License is distributed on an "AS IS" BASIS,
1369419bafSAndrew Jeffery   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1469419bafSAndrew Jeffery   See the License for the specific language governing permissions and
1569419bafSAndrew Jeffery   limitations under the License.
1669419bafSAndrew Jeffery"""
1769419bafSAndrew Jefferyimport argparse
1869419bafSAndrew Jefferyimport requests
1969419bafSAndrew Jefferyimport getpass
2069419bafSAndrew Jefferyimport json
2169419bafSAndrew Jefferyimport os
2269419bafSAndrew Jefferyimport urllib3
2369419bafSAndrew Jefferyimport time, datetime
2469419bafSAndrew Jefferyimport binascii
2569419bafSAndrew Jefferyimport subprocess
2669419bafSAndrew Jefferyimport platform
2769419bafSAndrew Jefferyimport zipfile
2869419bafSAndrew Jefferyimport tarfile
2969419bafSAndrew Jefferyimport tempfile
3069419bafSAndrew Jefferyimport hashlib
3169419bafSAndrew Jefferyimport re
3269419bafSAndrew Jefferyimport uuid
3369419bafSAndrew Jefferyimport ssl
3469419bafSAndrew Jefferyimport socket
3569419bafSAndrew Jefferyimport select
3669419bafSAndrew Jefferyimport http.client
3769419bafSAndrew Jefferyfrom subprocess import check_output
3869419bafSAndrew Jefferyimport traceback
3969419bafSAndrew Jeffery
4069419bafSAndrew Jeffery
4169419bafSAndrew JefferyMAX_NBD_PACKET_SIZE = 131088
4269419bafSAndrew JefferyjsonHeader = {'Content-Type' : 'application/json'}
4369419bafSAndrew JefferyxAuthHeader = {}
4469419bafSAndrew JefferybaseTimeout = 60
4569419bafSAndrew JefferyserverTypeMap = {
4669419bafSAndrew Jeffery        'ActiveDirectory' : 'active_directory',
4769419bafSAndrew Jeffery        'OpenLDAP' : 'openldap'
4869419bafSAndrew Jeffery        }
4969419bafSAndrew Jeffery
5069419bafSAndrew Jefferyclass NBDPipe:
5169419bafSAndrew Jeffery
5269419bafSAndrew Jeffery    def openHTTPSocket(self,args):
5369419bafSAndrew Jeffery
5469419bafSAndrew Jeffery        try:
5569419bafSAndrew Jeffery            _create_unverified_https_context = ssl._create_unverified_context
5669419bafSAndrew Jeffery        except AttributeError:
5769419bafSAndrew Jeffery            # Legacy Python that doesn't verify HTTPS certificates by default
5869419bafSAndrew Jeffery            pass
5969419bafSAndrew Jeffery        else:
6069419bafSAndrew Jeffery            # Handle target environment that doesn't support HTTPS verification
6169419bafSAndrew Jeffery            ssl._create_default_https_context = _create_unverified_https_context
6269419bafSAndrew Jeffery
6369419bafSAndrew Jeffery
6469419bafSAndrew Jeffery        token = gettoken(args)
6569419bafSAndrew Jeffery        self.conn = http.client.HTTPSConnection(args.host,port=443)
6669419bafSAndrew Jeffery
6769419bafSAndrew Jeffery        uri = "/redfish/v1/Systems/system/LogServices/Dump/attachment/"+args.dumpNum
6869419bafSAndrew Jeffery
6969419bafSAndrew Jeffery        self.conn.request("GET",uri, headers={"X-Auth-Token":token})
7069419bafSAndrew Jeffery
7169419bafSAndrew Jeffery    def openTCPSocket(self):
7269419bafSAndrew Jeffery        # Create a TCP/IP socket
7369419bafSAndrew Jeffery        self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
7469419bafSAndrew Jeffery        # Connect the socket to the port where the server is listening
7569419bafSAndrew Jeffery        server_address = ('localhost', 1043)
7669419bafSAndrew Jeffery        self.tcp.connect(server_address)
7769419bafSAndrew Jeffery
7869419bafSAndrew Jeffery    def waitformessage(self):
7969419bafSAndrew Jeffery        inputs = [self.conn.sock,self.tcp]
8069419bafSAndrew Jeffery        outputs = []
8169419bafSAndrew Jeffery        message_queues = {}
8269419bafSAndrew Jeffery        while True:
8369419bafSAndrew Jeffery            readable, writable, exceptional = select.select(
8469419bafSAndrew Jeffery                    inputs, outputs, inputs)
8569419bafSAndrew Jeffery
8669419bafSAndrew Jeffery            for s in readable:
8769419bafSAndrew Jeffery                if s is self.conn.sock:
8869419bafSAndrew Jeffery
8969419bafSAndrew Jeffery                    data = self.conn.sock.recv(MAX_NBD_PACKET_SIZE)
9069419bafSAndrew Jeffery                    print("<<HTTP")
9169419bafSAndrew Jeffery                    if data:
9269419bafSAndrew Jeffery                        self.tcp.send(data)
9369419bafSAndrew Jeffery                    else:
9469419bafSAndrew Jeffery                        print ("BMC Closed the connection")
9569419bafSAndrew Jeffery                        self.conn.close()
9669419bafSAndrew Jeffery                        self.tcp.close()
9769419bafSAndrew Jeffery                        sys.exit(1)
9869419bafSAndrew Jeffery                elif s is self.tcp:
9969419bafSAndrew Jeffery                    data = self.tcp.recv(MAX_NBD_PACKET_SIZE)
10069419bafSAndrew Jeffery                    print(">>TCP")
10169419bafSAndrew Jeffery                    if data:
10269419bafSAndrew Jeffery                        self.conn.sock.send(data)
10369419bafSAndrew Jeffery                    else:
10469419bafSAndrew Jeffery                        print("NBD server closed the connection")
10569419bafSAndrew Jeffery                        self.conn.sock.close()
10669419bafSAndrew Jeffery                        self.tcp.close()
10769419bafSAndrew Jeffery                        sys.exit(1)
10869419bafSAndrew Jeffery            for s in exceptional:
10969419bafSAndrew Jeffery                inputs.remove(s)
11069419bafSAndrew Jeffery                print("Exceptional closing the socket")
11169419bafSAndrew Jeffery                s.close()
11269419bafSAndrew Jeffery
11369419bafSAndrew Jefferydef getsize(host,args,session):
11469419bafSAndrew Jeffery    url = "https://"+host+"/redfish/v1/Systems/system/LogServices/Dump/Entries/"+str(args.dumpNum)
11569419bafSAndrew Jeffery    try:
11669419bafSAndrew Jeffery        resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
11769419bafSAndrew Jeffery        if resp.status_code==200:
1184e178110SAsmitha Karunanithi            size = resp.json()['AdditionalDataSizeBytes']
11969419bafSAndrew Jeffery            return size
12069419bafSAndrew Jeffery        else:
12169419bafSAndrew Jeffery            return "Failed get Size"
12269419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
12369419bafSAndrew Jeffery        return connectionErrHandler(args.json, "Timeout", None)
12469419bafSAndrew Jeffery
12569419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
12669419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
12769419bafSAndrew Jeffery
12869419bafSAndrew Jefferydef gettoken(args):
12969419bafSAndrew Jeffery   mysess = requests.session()
13069419bafSAndrew Jeffery   resp = mysess.post('https://'+args.host+'/login', headers=jsonHeader,json={"data":[args.user,args.PW]},verify=False)
13169419bafSAndrew Jeffery   if resp.status_code == 200:
13269419bafSAndrew Jeffery       cookie = resp.headers['Set-Cookie']
13369419bafSAndrew Jeffery       match = re.search('SESSION=(\w+);', cookie)
13469419bafSAndrew Jeffery       return match.group(1)
13569419bafSAndrew Jeffery
13669419bafSAndrew Jeffery
13769419bafSAndrew Jeffery
13869419bafSAndrew Jefferydef get_pid(name):
13969419bafSAndrew Jeffery    try:
14069419bafSAndrew Jeffery        pid = map(int, check_output(["pidof", "-s",name]))
14169419bafSAndrew Jeffery    except Exception:
14269419bafSAndrew Jeffery        pid = 0
14369419bafSAndrew Jeffery
14469419bafSAndrew Jeffery    return pid
14569419bafSAndrew Jeffery
14669419bafSAndrew Jefferydef findThisProcess( process_name ):
14769419bafSAndrew Jeffery  ps     = subprocess.Popen("ps -eaf | grep "+process_name, shell=True, stdout=subprocess.PIPE)
14869419bafSAndrew Jeffery  output = ps.stdout.read()
14969419bafSAndrew Jeffery  ps.stdout.close()
15069419bafSAndrew Jeffery  ps.wait()
15169419bafSAndrew Jeffery  pid = get_pid(process_name)
15269419bafSAndrew Jeffery  return output
15369419bafSAndrew Jeffery
15469419bafSAndrew Jefferydef isThisProcessRunning( process_name ):
15569419bafSAndrew Jeffery  pid = get_pid(process_name)
15669419bafSAndrew Jeffery  if (pid == 0 ):
15769419bafSAndrew Jeffery    return False
15869419bafSAndrew Jeffery  else:
15969419bafSAndrew Jeffery    return True
16069419bafSAndrew Jeffery
16169419bafSAndrew Jefferydef NBDSetup(host,args,session):
16269419bafSAndrew Jeffery    user=os.getenv("SUDO_USER")
16369419bafSAndrew Jeffery    if user is None:
16469419bafSAndrew Jeffery        path = os.getcwd()
16569419bafSAndrew Jeffery        nbdServerPath = path + "/nbd-server"
16669419bafSAndrew Jeffery        if not os.path.exists(nbdServerPath):
16769419bafSAndrew Jeffery            print("Error: this program did not run as sudo!\nplease copy nbd-server to  current directory and run script again")
16869419bafSAndrew Jeffery            exit()
16969419bafSAndrew Jeffery
17069419bafSAndrew Jeffery    if isThisProcessRunning('nbd-server') == True:
17169419bafSAndrew Jeffery        print("nbd-server already Running! killing the nbd-server")
17269419bafSAndrew Jeffery        os.system('killall nbd-server')
17369419bafSAndrew Jeffery
17469419bafSAndrew Jeffery    if (args.dumpSaveLoc is not None):
17569419bafSAndrew Jeffery        if(os.path.exists(args.dumpSaveLoc)):
17669419bafSAndrew Jeffery            print("Error: File already exists.")
17769419bafSAndrew Jeffery            exit()
17869419bafSAndrew Jeffery
17969419bafSAndrew Jeffery    fp= open(args.dumpSaveLoc,"w")
18069419bafSAndrew Jeffery    sizeInBytes = getsize(host,args,session)
18169419bafSAndrew Jeffery    #Round off size to mutiples of 1024
18269419bafSAndrew Jeffery    size = int(sizeInBytes)
18369419bafSAndrew Jeffery    mod = size % 1024
18469419bafSAndrew Jeffery    if mod :
18569419bafSAndrew Jeffery        roundoff = 1024 - mod
18669419bafSAndrew Jeffery        size = size + roundoff
18769419bafSAndrew Jeffery
18869419bafSAndrew Jeffery    cmd = 'chmod 777 ' + args.dumpSaveLoc
18969419bafSAndrew Jeffery    os.system(cmd)
19069419bafSAndrew Jeffery
19169419bafSAndrew Jeffery    #Run truncate to create file with given size
19269419bafSAndrew Jeffery    cmd = 'truncate -s ' + str(size) + ' '+ args.dumpSaveLoc
19369419bafSAndrew Jeffery    os.system(cmd)
19469419bafSAndrew Jeffery
19569419bafSAndrew Jeffery    if user is None:
19669419bafSAndrew Jeffery        cmd = './nbd-server 1043 '+ args.dumpSaveLoc
19769419bafSAndrew Jeffery    else:
19869419bafSAndrew Jeffery        cmd = 'nbd-server 1043 '+ args.dumpSaveLoc
19969419bafSAndrew Jeffery    os.system(cmd)
20069419bafSAndrew Jeffery
20169419bafSAndrew Jeffery
20269419bafSAndrew Jefferydef hilight(textToColor, color, bold):
20369419bafSAndrew Jeffery    """
20469419bafSAndrew Jeffery         Used to add highlights to various text for displaying in a terminal
20569419bafSAndrew Jeffery
20669419bafSAndrew Jeffery         @param textToColor: string, the text to be colored
20769419bafSAndrew Jeffery         @param color: string, used to color the text red or green
20869419bafSAndrew Jeffery         @param bold: boolean, used to bold the textToColor
20969419bafSAndrew Jeffery         @return: Buffered reader containing the modified string.
21069419bafSAndrew Jeffery    """
21169419bafSAndrew Jeffery    if(sys.platform.__contains__("win")):
21269419bafSAndrew Jeffery        if(color == "red"):
21369419bafSAndrew Jeffery            os.system('color 04')
21469419bafSAndrew Jeffery        elif(color == "green"):
21569419bafSAndrew Jeffery            os.system('color 02')
21669419bafSAndrew Jeffery        else:
21769419bafSAndrew Jeffery            os.system('color') #reset to default
21869419bafSAndrew Jeffery        return textToColor
21969419bafSAndrew Jeffery    else:
22069419bafSAndrew Jeffery        attr = []
22169419bafSAndrew Jeffery        if(color == "red"):
22269419bafSAndrew Jeffery            attr.append('31')
22369419bafSAndrew Jeffery        elif(color == "green"):
22469419bafSAndrew Jeffery            attr.append('32')
22569419bafSAndrew Jeffery        else:
22669419bafSAndrew Jeffery            attr.append('0')
22769419bafSAndrew Jeffery        if bold:
22869419bafSAndrew Jeffery            attr.append('1')
22969419bafSAndrew Jeffery        else:
23069419bafSAndrew Jeffery            attr.append('0')
23169419bafSAndrew Jeffery        return '\x1b[%sm%s\x1b[0m' % (';'.join(attr),textToColor)
23269419bafSAndrew Jeffery
23369419bafSAndrew Jefferydef connectionErrHandler(jsonFormat, errorStr, err):
23469419bafSAndrew Jeffery    """
23569419bafSAndrew Jeffery         Error handler various connection errors to bmcs
23669419bafSAndrew Jeffery
23769419bafSAndrew Jeffery         @param jsonFormat: boolean, used to output in json format with an error code.
23869419bafSAndrew Jeffery         @param errorStr: string, used to color the text red or green
23969419bafSAndrew Jeffery         @param err: string, the text from the exception
24069419bafSAndrew Jeffery    """
24169419bafSAndrew Jeffery    if errorStr == "Timeout":
24269419bafSAndrew Jeffery        if not jsonFormat:
24369419bafSAndrew Jeffery            return("FQPSPIN0000M: Connection timed out. Ensure you have network connectivity to the bmc")
24469419bafSAndrew Jeffery        else:
24569419bafSAndrew Jeffery            conerror = {}
24669419bafSAndrew Jeffery            conerror['CommonEventID'] = 'FQPSPIN0000M'
24769419bafSAndrew Jeffery            conerror['sensor']="N/A"
24869419bafSAndrew Jeffery            conerror['state']="N/A"
24969419bafSAndrew Jeffery            conerror['additionalDetails'] = "N/A"
25069419bafSAndrew Jeffery            conerror['Message']="Connection timed out. Ensure you have network connectivity to the BMC"
25169419bafSAndrew Jeffery            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."
25269419bafSAndrew Jeffery            conerror['Serviceable']="Yes"
25369419bafSAndrew Jeffery            conerror['CallHomeCandidate']= "No"
25469419bafSAndrew Jeffery            conerror['Severity'] = "Critical"
25569419bafSAndrew Jeffery            conerror['EventType'] = "Communication Failure/Timeout"
25669419bafSAndrew Jeffery            conerror['VMMigrationFlag'] = "Yes"
25769419bafSAndrew Jeffery            conerror["AffectedSubsystem"] = "Interconnect (Networking)"
25869419bafSAndrew Jeffery            conerror["timestamp"] = str(int(time.time()))
25969419bafSAndrew Jeffery            conerror["UserAction"] = "Verify network connectivity between the two systems and the bmc is functional."
26069419bafSAndrew Jeffery            eventdict = {}
26169419bafSAndrew Jeffery            eventdict['event0'] = conerror
26269419bafSAndrew Jeffery            eventdict['numAlerts'] = '1'
26369419bafSAndrew Jeffery            errorMessageStr = errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
26469419bafSAndrew Jeffery            return(errorMessageStr)
26569419bafSAndrew Jeffery    elif errorStr == "ConnectionError":
26669419bafSAndrew Jeffery        if not jsonFormat:
26769419bafSAndrew Jeffery            return("FQPSPIN0001M: " + str(err))
26869419bafSAndrew Jeffery        else:
26969419bafSAndrew Jeffery            conerror = {}
27069419bafSAndrew Jeffery            conerror['CommonEventID'] = 'FQPSPIN0001M'
27169419bafSAndrew Jeffery            conerror['sensor']="N/A"
27269419bafSAndrew Jeffery            conerror['state']="N/A"
27369419bafSAndrew Jeffery            conerror['additionalDetails'] = str(err)
27469419bafSAndrew Jeffery            conerror['Message']="Connection Error. View additional details for more information"
27569419bafSAndrew Jeffery            conerror['LengthyDescription'] = "A connection error to the specified BMC occurred and additional details are provided. Review these details to resolve the issue."
27669419bafSAndrew Jeffery            conerror['Serviceable']="Yes"
27769419bafSAndrew Jeffery            conerror['CallHomeCandidate']= "No"
27869419bafSAndrew Jeffery            conerror['Severity'] = "Critical"
27969419bafSAndrew Jeffery            conerror['EventType'] = "Communication Failure/Timeout"
28069419bafSAndrew Jeffery            conerror['VMMigrationFlag'] = "Yes"
28169419bafSAndrew Jeffery            conerror["AffectedSubsystem"] = "Interconnect (Networking)"
28269419bafSAndrew Jeffery            conerror["timestamp"] = str(int(time.time()))
28369419bafSAndrew Jeffery            conerror["UserAction"] = "Correct the issue highlighted in additional details and try again"
28469419bafSAndrew Jeffery            eventdict = {}
28569419bafSAndrew Jeffery            eventdict['event0'] = conerror
28669419bafSAndrew Jeffery            eventdict['numAlerts'] = '1'
28769419bafSAndrew Jeffery            errorMessageStr = json.dumps(eventdict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
28869419bafSAndrew Jeffery            return(errorMessageStr)
28969419bafSAndrew Jeffery
29069419bafSAndrew Jeffery    else:
29169419bafSAndrew Jeffery        return("Unknown Error: "+ str(err))
29269419bafSAndrew Jeffery
29369419bafSAndrew Jeffery
29469419bafSAndrew Jefferydef setColWidth(keylist, numCols, dictForOutput, colNames):
29569419bafSAndrew Jeffery    """
29669419bafSAndrew Jeffery         Sets the output width of the columns to display
29769419bafSAndrew Jeffery
29869419bafSAndrew Jeffery         @param keylist: list, list of strings representing the keys for the dictForOutput
29969419bafSAndrew Jeffery         @param numcols: the total number of columns in the final output
30069419bafSAndrew Jeffery         @param dictForOutput: dictionary, contains the information to print to the screen
30169419bafSAndrew Jeffery         @param colNames: list, The strings to use for the column headings, in order of the keylist
30269419bafSAndrew Jeffery         @return: A list of the column widths for each respective column.
30369419bafSAndrew Jeffery    """
30469419bafSAndrew Jeffery    colWidths = []
30569419bafSAndrew Jeffery    for x in range(0, numCols):
30669419bafSAndrew Jeffery        colWidths.append(0)
30769419bafSAndrew Jeffery    for key in dictForOutput:
30869419bafSAndrew Jeffery        for x in range(0, numCols):
30969419bafSAndrew Jeffery            colWidths[x] = max(colWidths[x], len(str(dictForOutput[key][keylist[x]])))
31069419bafSAndrew Jeffery
31169419bafSAndrew Jeffery    for x in range(0, numCols):
31269419bafSAndrew Jeffery        colWidths[x] = max(colWidths[x], len(colNames[x])) +2
31369419bafSAndrew Jeffery
31469419bafSAndrew Jeffery    return colWidths
31569419bafSAndrew Jeffery
31669419bafSAndrew Jefferydef loadPolicyTable(pathToPolicyTable):
31769419bafSAndrew Jeffery    """
31869419bafSAndrew Jeffery         loads a json based policy table into a dictionary
31969419bafSAndrew Jeffery
32069419bafSAndrew Jeffery         @param value: boolean, the value to convert
32169419bafSAndrew Jeffery         @return: A string of "Yes" or "No"
32269419bafSAndrew Jeffery    """
32369419bafSAndrew Jeffery    policyTable = {}
32469419bafSAndrew Jeffery    if(os.path.exists(pathToPolicyTable)):
32569419bafSAndrew Jeffery        with open(pathToPolicyTable, 'r') as stream:
32669419bafSAndrew Jeffery            try:
32769419bafSAndrew Jeffery                contents =json.load(stream)
32869419bafSAndrew Jeffery                policyTable = contents['events']
32969419bafSAndrew Jeffery            except Exception as err:
33069419bafSAndrew Jeffery                print(err)
33169419bafSAndrew Jeffery    return policyTable
33269419bafSAndrew Jeffery
33369419bafSAndrew Jeffery
33469419bafSAndrew Jefferydef boolToString(value):
33569419bafSAndrew Jeffery    """
33669419bafSAndrew Jeffery         converts a boolean value to a human readable string value
33769419bafSAndrew Jeffery
33869419bafSAndrew Jeffery         @param value: boolean, the value to convert
33969419bafSAndrew Jeffery         @return: A string of "Yes" or "No"
34069419bafSAndrew Jeffery    """
34169419bafSAndrew Jeffery    if(value):
34269419bafSAndrew Jeffery        return "Yes"
34369419bafSAndrew Jeffery    else:
34469419bafSAndrew Jeffery        return "No"
34569419bafSAndrew Jeffery
34669419bafSAndrew Jefferydef stringToInt(text):
34769419bafSAndrew Jeffery    """
34869419bafSAndrew Jeffery        returns an integer if the string can be converted, otherwise returns the string
34969419bafSAndrew Jeffery
35069419bafSAndrew Jeffery        @param text: the string to try to convert to an integer
35169419bafSAndrew Jeffery    """
35269419bafSAndrew Jeffery    if text.isdigit():
35369419bafSAndrew Jeffery        return int(text)
35469419bafSAndrew Jeffery    else:
35569419bafSAndrew Jeffery        return text
35669419bafSAndrew Jeffery
35769419bafSAndrew Jefferydef naturalSort(text):
35869419bafSAndrew Jeffery    """
35969419bafSAndrew Jeffery        provides a way to naturally sort a list
36069419bafSAndrew Jeffery
36169419bafSAndrew Jeffery        @param text: the key to convert for sorting
36269419bafSAndrew Jeffery        @return list containing the broken up string parts by integers and strings
36369419bafSAndrew Jeffery    """
36469419bafSAndrew Jeffery    stringPartList = []
36569419bafSAndrew Jeffery    for c in re.split('(\d+)', text):
36669419bafSAndrew Jeffery        stringPartList.append(stringToInt(c))
36769419bafSAndrew Jeffery    return stringPartList
36869419bafSAndrew Jeffery
36969419bafSAndrew Jefferydef tableDisplay(keylist, colNames, output):
37069419bafSAndrew Jeffery    """
37169419bafSAndrew Jeffery         Logs into the BMC and creates a session
37269419bafSAndrew Jeffery
37369419bafSAndrew Jeffery         @param keylist: list, keys for the output dictionary, ordered by colNames
37469419bafSAndrew Jeffery         @param colNames: Names for the Table of the columns
37569419bafSAndrew Jeffery         @param output: The dictionary of data to display
37669419bafSAndrew Jeffery         @return: Session object
37769419bafSAndrew Jeffery    """
37869419bafSAndrew Jeffery    colWidth = setColWidth(keylist, len(colNames), output, colNames)
37969419bafSAndrew Jeffery    row = ""
38069419bafSAndrew Jeffery    outputText = ""
38169419bafSAndrew Jeffery    for i in range(len(colNames)):
38269419bafSAndrew Jeffery        if (i != 0): row = row + "| "
38369419bafSAndrew Jeffery        row = row + colNames[i].ljust(colWidth[i])
38469419bafSAndrew Jeffery    outputText += row + "\n"
38569419bafSAndrew Jeffery
38669419bafSAndrew Jeffery    output_keys = list(output.keys())
38769419bafSAndrew Jeffery    output_keys.sort(key=naturalSort)
38869419bafSAndrew Jeffery    for key in output_keys:
38969419bafSAndrew Jeffery        row = ""
39069419bafSAndrew Jeffery        for i in range(len(keylist)):
39169419bafSAndrew Jeffery            if (i != 0): row = row + "| "
39269419bafSAndrew Jeffery            row = row + output[key][keylist[i]].ljust(colWidth[i])
39369419bafSAndrew Jeffery        outputText += row + "\n"
39469419bafSAndrew Jeffery
39569419bafSAndrew Jeffery    return outputText
39669419bafSAndrew Jeffery
39769419bafSAndrew Jefferydef checkFWactivation(host, args, session):
39869419bafSAndrew Jeffery    """
39969419bafSAndrew Jeffery        Checks the software inventory for an image that is being activated.
40069419bafSAndrew Jeffery
40169419bafSAndrew Jeffery        @return: True if an image is being activated, false is no activations are happening
40269419bafSAndrew Jeffery    """
40369419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/software/enumerate"
40469419bafSAndrew Jeffery    try:
40569419bafSAndrew Jeffery        resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
40669419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
40769419bafSAndrew Jeffery        print(connectionErrHandler(args.json, "Timeout", None))
40869419bafSAndrew Jeffery        return(True)
40969419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
41069419bafSAndrew Jeffery        print( connectionErrHandler(args.json, "ConnectionError", err))
41169419bafSAndrew Jeffery        return True
41269419bafSAndrew Jeffery    fwInfo = resp.json()['data']
41369419bafSAndrew Jeffery    for key in fwInfo:
41469419bafSAndrew Jeffery        if 'Activation' in fwInfo[key]:
41569419bafSAndrew Jeffery            if 'Activating' in fwInfo[key]['Activation'] or 'Activating' in fwInfo[key]['RequestedActivation']:
41669419bafSAndrew Jeffery                return True
41769419bafSAndrew Jeffery    return False
41869419bafSAndrew Jeffery
41969419bafSAndrew Jefferydef login(host, username, pw,jsonFormat, allowExpiredPassword):
42069419bafSAndrew Jeffery    """
42169419bafSAndrew Jeffery         Logs into the BMC and creates a session
42269419bafSAndrew Jeffery
42369419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc to log into
42469419bafSAndrew Jeffery         @param username: The user name for the bmc to log into
42569419bafSAndrew Jeffery         @param pw: The password for the BMC to log into
42669419bafSAndrew Jeffery         @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true.
42769419bafSAndrew Jeffery         @param allowExpiredPassword: true, if the requested operation should
42869419bafSAndrew Jeffery                be allowed when the password is expired
42969419bafSAndrew Jeffery         @return: Session object
43069419bafSAndrew Jeffery    """
43169419bafSAndrew Jeffery    if(jsonFormat==False):
43269419bafSAndrew Jeffery        print("Attempting login...")
43369419bafSAndrew Jeffery    mysess = requests.session()
43469419bafSAndrew Jeffery    try:
43569419bafSAndrew Jeffery        r = mysess.post('https://'+host+'/login', headers=jsonHeader, json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
43669419bafSAndrew Jeffery        if r.status_code == 200:
43769419bafSAndrew Jeffery            cookie = r.headers['Set-Cookie']
43869419bafSAndrew Jeffery            match = re.search('SESSION=(\w+);', cookie)
43969419bafSAndrew Jeffery            if match:
44069419bafSAndrew Jeffery                xAuthHeader['X-Auth-Token'] = match.group(1)
44169419bafSAndrew Jeffery                jsonHeader.update(xAuthHeader)
44269419bafSAndrew Jeffery            loginMessage = json.loads(r.text)
44369419bafSAndrew Jeffery            if (loginMessage['status'] != "ok"):
44469419bafSAndrew Jeffery                print(loginMessage["data"]["description"].encode('utf-8'))
44569419bafSAndrew Jeffery                sys.exit(1)
44669419bafSAndrew Jeffery            if (('extendedMessage' in r.json()) and
44769419bafSAndrew Jeffery                ('The password for this account must be changed' in r.json()['extendedMessage'])):
44869419bafSAndrew Jeffery                if not allowExpiredPassword:
44969419bafSAndrew Jeffery                    print("The password for this system has expired and must be changed"+
45069419bafSAndrew Jeffery                            "\nsee openbmctool.py set_password --help")
45169419bafSAndrew Jeffery                    logout(host, username, pw, mysess, jsonFormat)
45269419bafSAndrew Jeffery                    sys.exit(1)
45369419bafSAndrew Jeffery#         if(sys.version_info < (3,0)):
45469419bafSAndrew Jeffery#             urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
45569419bafSAndrew Jeffery#         if sys.version_info >= (3,0):
45669419bafSAndrew Jeffery#             requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
45769419bafSAndrew Jeffery            return mysess
45869419bafSAndrew Jeffery        else:
45969419bafSAndrew Jeffery            return None
46069419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
46169419bafSAndrew Jeffery        return (connectionErrHandler(jsonFormat, "Timeout", None))
46269419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
46369419bafSAndrew Jeffery        return (connectionErrHandler(jsonFormat, "ConnectionError", err))
46469419bafSAndrew Jeffery
46569419bafSAndrew Jeffery
46669419bafSAndrew Jefferydef logout(host, username, pw, session, jsonFormat):
46769419bafSAndrew Jeffery    """
46869419bafSAndrew Jeffery         Logs out of the bmc and terminates the session
46969419bafSAndrew Jeffery
47069419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc to log out of
47169419bafSAndrew Jeffery         @param username: The user name for the bmc to log out of
47269419bafSAndrew Jeffery         @param pw: The password for the BMC to log out of
47369419bafSAndrew Jeffery         @param session: the active session to use
47469419bafSAndrew Jeffery         @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true.
47569419bafSAndrew Jeffery    """
47669419bafSAndrew Jeffery    try:
47769419bafSAndrew Jeffery        r = session.post('https://'+host+'/logout', headers=jsonHeader,json = {"data": [username, pw]}, verify=False, timeout=baseTimeout)
47869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
47969419bafSAndrew Jeffery        print(connectionErrHandler(jsonFormat, "Timeout", None))
48069419bafSAndrew Jeffery
48169419bafSAndrew Jeffery    if(jsonFormat==False):
48269419bafSAndrew Jeffery        if r.status_code == 200:
48369419bafSAndrew Jeffery            print('User ' +username + ' has been logged out')
48469419bafSAndrew Jeffery
48569419bafSAndrew Jeffery
48669419bafSAndrew Jefferydef fru(host, args, session):
48769419bafSAndrew Jeffery    """
48869419bafSAndrew Jeffery         prints out the system inventory. deprecated see fruPrint and fruList
48969419bafSAndrew Jeffery
49069419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
49169419bafSAndrew Jeffery         @param args: contains additional arguments used by the fru sub command
49269419bafSAndrew Jeffery         @param session: the active session to use
49369419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
49469419bafSAndrew Jeffery    """
49569419bafSAndrew Jeffery    #url="https://"+host+"/org/openbmc/inventory/system/chassis/enumerate"
49669419bafSAndrew Jeffery
49769419bafSAndrew Jeffery    #print(url)
49869419bafSAndrew Jeffery    #res = session.get(url, headers=httpHeader, verify=False)
49969419bafSAndrew Jeffery    #print(res.text)
50069419bafSAndrew Jeffery    #sample = res.text
50169419bafSAndrew Jeffery
50269419bafSAndrew Jeffery    #inv_list = json.loads(sample)["data"]
50369419bafSAndrew Jeffery
50469419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
50569419bafSAndrew Jeffery    try:
50669419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
50769419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
50869419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
50969419bafSAndrew Jeffery
51069419bafSAndrew Jeffery    sample = res.text
51169419bafSAndrew Jeffery#     inv_list.update(json.loads(sample)["data"])
51269419bafSAndrew Jeffery#
51369419bafSAndrew Jeffery#     #determine column width's
51469419bafSAndrew Jeffery#     colNames = ["FRU Name", "FRU Type", "Has Fault", "Is FRU", "Present", "Version"]
51569419bafSAndrew Jeffery#     colWidths = setColWidth(["FRU Name", "fru_type", "fault", "is_fru", "present", "version"], 6, inv_list, colNames)
51669419bafSAndrew Jeffery#
51769419bafSAndrew Jeffery#     print("FRU Name".ljust(colWidths[0])+ "FRU Type".ljust(colWidths[1]) + "Has Fault".ljust(colWidths[2]) + "Is FRU".ljust(colWidths[3])+
51869419bafSAndrew Jeffery#           "Present".ljust(colWidths[4]) + "Version".ljust(colWidths[5]))
51969419bafSAndrew Jeffery#     format the output
52069419bafSAndrew Jeffery#     for key in sorted(inv_list.keys()):
52169419bafSAndrew Jeffery#         keyParts = key.split("/")
52269419bafSAndrew Jeffery#         isFRU = "True" if (inv_list[key]["is_fru"]==1) else "False"
52369419bafSAndrew Jeffery#
52469419bafSAndrew Jeffery#         fruEntry = (keyParts[len(keyParts) - 1].ljust(colWidths[0]) + inv_list[key]["fru_type"].ljust(colWidths[1])+
52569419bafSAndrew Jeffery#                inv_list[key]["fault"].ljust(colWidths[2])+isFRU.ljust(colWidths[3])+
52669419bafSAndrew Jeffery#                inv_list[key]["present"].ljust(colWidths[4])+ inv_list[key]["version"].ljust(colWidths[5]))
52769419bafSAndrew Jeffery#         if(isTTY):
52869419bafSAndrew Jeffery#             if(inv_list[key]["is_fru"] == 1):
52969419bafSAndrew Jeffery#                 color = "green"
53069419bafSAndrew Jeffery#                 bold = True
53169419bafSAndrew Jeffery#             else:
53269419bafSAndrew Jeffery#                 color='black'
53369419bafSAndrew Jeffery#                 bold = False
53469419bafSAndrew Jeffery#             fruEntry = hilight(fruEntry, color, bold)
53569419bafSAndrew Jeffery#         print (fruEntry)
53669419bafSAndrew Jeffery    return sample
53769419bafSAndrew Jeffery
53869419bafSAndrew Jefferydef fruPrint(host, args, session):
53969419bafSAndrew Jeffery    """
54069419bafSAndrew Jeffery         prints out all inventory
54169419bafSAndrew Jeffery
54269419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
54369419bafSAndrew Jeffery         @param args: contains additional arguments used by the fru sub command
54469419bafSAndrew Jeffery         @param session: the active session to use
54569419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
54669419bafSAndrew Jeffery         @return returns the total fru list.
54769419bafSAndrew Jeffery    """
54869419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
54969419bafSAndrew Jeffery    try:
55069419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
55169419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
55269419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
55369419bafSAndrew Jeffery
55469419bafSAndrew Jeffery    frulist={}
55569419bafSAndrew Jeffery#     print(res.text)
55669419bafSAndrew Jeffery    if res.status_code==200:
55769419bafSAndrew Jeffery        frulist['Hardware'] = res.json()['data']
55869419bafSAndrew Jeffery    else:
55969419bafSAndrew Jeffery        if not args.json:
56069419bafSAndrew Jeffery            return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
56169419bafSAndrew Jeffery        else:
56269419bafSAndrew Jeffery            return res.json()
56369419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/software/enumerate"
56469419bafSAndrew Jeffery    try:
56569419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
56669419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
56769419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
56869419bafSAndrew Jeffery#     print(res.text)
56969419bafSAndrew Jeffery    if res.status_code==200:
57069419bafSAndrew Jeffery        frulist['Software'] = res.json()['data']
57169419bafSAndrew Jeffery    else:
57269419bafSAndrew Jeffery        if not args.json():
57369419bafSAndrew Jeffery            return "Error retrieving the system inventory. BMC message: {msg}".format(msg=res.json()['message'])
57469419bafSAndrew Jeffery        else:
57569419bafSAndrew Jeffery            return res.json()
57669419bafSAndrew Jeffery    return frulist
57769419bafSAndrew Jeffery
57869419bafSAndrew Jeffery
57969419bafSAndrew Jefferydef fruList(host, args, session):
58069419bafSAndrew Jeffery    """
58169419bafSAndrew Jeffery         prints out all inventory or only a specific specified item
58269419bafSAndrew Jeffery
58369419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
58469419bafSAndrew Jeffery         @param args: contains additional arguments used by the fru sub command
58569419bafSAndrew Jeffery         @param session: the active session to use
58669419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
58769419bafSAndrew Jeffery    """
58869419bafSAndrew Jeffery    if(args.items==True):
58969419bafSAndrew Jeffery        return fruPrint(host, args, session)
59069419bafSAndrew Jeffery    else:
59169419bafSAndrew Jeffery        return fruPrint(host, args, session)
59269419bafSAndrew Jeffery
59369419bafSAndrew Jeffery
59469419bafSAndrew Jeffery
59569419bafSAndrew Jefferydef fruStatus(host, args, session):
59669419bafSAndrew Jeffery    """
59769419bafSAndrew Jeffery         prints out the status of all FRUs
59869419bafSAndrew Jeffery
59969419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
60069419bafSAndrew Jeffery         @param args: contains additional arguments used by the fru sub command
60169419bafSAndrew Jeffery         @param session: the active session to use
60269419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
60369419bafSAndrew Jeffery    """
60469419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/inventory/enumerate"
60569419bafSAndrew Jeffery    try:
60669419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False)
60769419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
60869419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
60969419bafSAndrew Jeffery#     print(res.text)
61069419bafSAndrew Jeffery    frulist = res.json()['data']
61169419bafSAndrew Jeffery    frus = {}
61269419bafSAndrew Jeffery    for key in frulist:
61369419bafSAndrew Jeffery        component = frulist[key]
61469419bafSAndrew Jeffery        isFru = False
61569419bafSAndrew Jeffery        present = False
61669419bafSAndrew Jeffery        func = False
61769419bafSAndrew Jeffery        hasSels = False
61869419bafSAndrew Jeffery        keyPieces = key.split('/')
61969419bafSAndrew Jeffery        fruName = keyPieces[-1]
62069419bafSAndrew Jeffery        if 'core' in fruName: #associate cores to cpus
62169419bafSAndrew Jeffery            fruName = keyPieces[-2] + '-' + keyPieces[-1]
62269419bafSAndrew Jeffery        if 'Functional' in component:
62369419bafSAndrew Jeffery            if('Present' in component):
62469419bafSAndrew Jeffery                if 'FieldReplaceable' in component:
62569419bafSAndrew Jeffery                    if component['FieldReplaceable'] == 1:
62669419bafSAndrew Jeffery                        isFru = True
62769419bafSAndrew Jeffery                if "fan" in fruName:
62869419bafSAndrew Jeffery                    isFru = True;
62969419bafSAndrew Jeffery                if component['Present'] == 1:
63069419bafSAndrew Jeffery                    present = True
63169419bafSAndrew Jeffery                if component['Functional'] == 1:
63269419bafSAndrew Jeffery                    func = True
63369419bafSAndrew Jeffery                if ((key + "/fault") in frulist):
63469419bafSAndrew Jeffery                    hasSels = True;
63569419bafSAndrew Jeffery                if args.verbose:
63669419bafSAndrew Jeffery                    if hasSels:
63769419bafSAndrew Jeffery                        loglist = []
63869419bafSAndrew Jeffery                        faults = frulist[key+"/fault"]['endpoints']
63969419bafSAndrew Jeffery                        for item in faults:
64069419bafSAndrew Jeffery                            loglist.append(item.split('/')[-1])
64169419bafSAndrew Jeffery                        frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
64269419bafSAndrew Jeffery                    else:
64369419bafSAndrew Jeffery                        frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
64469419bafSAndrew Jeffery                else:
64569419bafSAndrew Jeffery                    frus[fruName] = {"compName": fruName, "Functional": boolToString(func), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
64669419bafSAndrew Jeffery        elif "power_supply" in fruName or "powersupply" in fruName:
64769419bafSAndrew Jeffery            if component['Present'] ==1:
64869419bafSAndrew Jeffery                present = True
64969419bafSAndrew Jeffery            isFru = True
65069419bafSAndrew Jeffery            if ((key + "/fault") in frulist):
65169419bafSAndrew Jeffery                hasSels = True;
65269419bafSAndrew Jeffery            if args.verbose:
65369419bafSAndrew Jeffery                if hasSels:
65469419bafSAndrew Jeffery                    loglist = []
65569419bafSAndrew Jeffery                    faults = frulist[key+"/fault"]['endpoints']
65669419bafSAndrew Jeffery                    for item in faults:
65769419bafSAndrew Jeffery                        loglist.append(item.split('/')[-1])
65869419bafSAndrew Jeffery                    frus[fruName] = {"compName": fruName, "Functional": "No", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": ', '.join(loglist).strip() }
65969419bafSAndrew Jeffery                else:
66069419bafSAndrew Jeffery                    frus[fruName] = {"compName": fruName, "Functional": "Yes", "Present":boolToString(present), "IsFru": boolToString(isFru), "selList": "None" }
66169419bafSAndrew Jeffery            else:
66269419bafSAndrew Jeffery                frus[fruName] = {"compName": fruName, "Functional": boolToString(not hasSels), "Present":boolToString(present), "IsFru": boolToString(isFru), "hasSEL": boolToString(hasSels) }
66369419bafSAndrew Jeffery    if not args.json:
66469419bafSAndrew Jeffery        if not args.verbose:
66569419bafSAndrew Jeffery            colNames = ["Component", "Is a FRU", "Present", "Functional", "Has Logs"]
66669419bafSAndrew Jeffery            keylist = ["compName", "IsFru", "Present", "Functional", "hasSEL"]
66769419bafSAndrew Jeffery        else:
66869419bafSAndrew Jeffery            colNames = ["Component", "Is a FRU", "Present", "Functional", "Assoc. Log Number(s)"]
66969419bafSAndrew Jeffery            keylist = ["compName", "IsFru", "Present", "Functional", "selList"]
67069419bafSAndrew Jeffery        return tableDisplay(keylist, colNames, frus)
67169419bafSAndrew Jeffery    else:
67269419bafSAndrew Jeffery        return str(json.dumps(frus, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
67369419bafSAndrew Jeffery
67469419bafSAndrew Jefferydef sensor(host, args, session):
67569419bafSAndrew Jeffery    """
67669419bafSAndrew Jeffery         prints out all sensors
67769419bafSAndrew Jeffery
67869419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
67969419bafSAndrew Jeffery         @param args: contains additional arguments used by the sensor sub command
68069419bafSAndrew Jeffery         @param session: the active session to use
68169419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
68269419bafSAndrew Jeffery    """
68369419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/sensors/enumerate"
68469419bafSAndrew Jeffery    try:
68569419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
68669419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
68769419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
68869419bafSAndrew Jeffery
68969419bafSAndrew Jeffery    #Get OCC status
69069419bafSAndrew Jeffery    url="https://"+host+"/org/open_power/control/enumerate"
69169419bafSAndrew Jeffery    try:
69269419bafSAndrew Jeffery        occres = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
69369419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
69469419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
69569419bafSAndrew Jeffery    if not args.json:
69669419bafSAndrew Jeffery        colNames = ['sensor', 'type', 'units', 'value', 'target']
69769419bafSAndrew Jeffery        sensors = res.json()["data"]
69869419bafSAndrew Jeffery        output = {}
69969419bafSAndrew Jeffery        for key in sensors:
70069419bafSAndrew Jeffery            senDict = {}
70169419bafSAndrew Jeffery            keyparts = key.split("/")
70269419bafSAndrew Jeffery
70369419bafSAndrew Jeffery            # Associations like the following also show up here:
70469419bafSAndrew Jeffery            # /xyz/openbmc_project/sensors/<type>/<name>/<assoc-name>
70569419bafSAndrew Jeffery            # Skip them.
70669419bafSAndrew Jeffery            # Note:  keyparts[0] = '' which is why there are 7 segments.
70769419bafSAndrew Jeffery            if len(keyparts) > 6:
70869419bafSAndrew Jeffery                continue
70969419bafSAndrew Jeffery
71069419bafSAndrew Jeffery            senDict['sensorName'] = keyparts[-1]
71169419bafSAndrew Jeffery            senDict['type'] = keyparts[-2]
71269419bafSAndrew Jeffery            try:
71369419bafSAndrew Jeffery                senDict['units'] = sensors[key]['Unit'].split('.')[-1]
71469419bafSAndrew Jeffery            except KeyError:
71569419bafSAndrew Jeffery                senDict['units'] = "N/A"
71669419bafSAndrew Jeffery            if('Scale' in sensors[key]):
71769419bafSAndrew Jeffery                scale = 10 ** sensors[key]['Scale']
71869419bafSAndrew Jeffery            else:
71969419bafSAndrew Jeffery                scale = 1
72069419bafSAndrew Jeffery            try:
72169419bafSAndrew Jeffery                senDict['value'] = str(sensors[key]['Value'] * scale)
72269419bafSAndrew Jeffery            except KeyError:
72369419bafSAndrew Jeffery                if 'value' in sensors[key]:
72469419bafSAndrew Jeffery                    senDict['value'] = sensors[key]['value']
72569419bafSAndrew Jeffery                else:
72669419bafSAndrew Jeffery                    senDict['value'] = "N/A"
72769419bafSAndrew Jeffery            if 'Target' in sensors[key]:
72869419bafSAndrew Jeffery                senDict['target'] = str(sensors[key]['Target'])
72969419bafSAndrew Jeffery            else:
73069419bafSAndrew Jeffery                senDict['target'] = 'N/A'
73169419bafSAndrew Jeffery            output[senDict['sensorName']] = senDict
73269419bafSAndrew Jeffery
73369419bafSAndrew Jeffery        occstatus = occres.json()["data"]
73469419bafSAndrew Jeffery        if '/org/open_power/control/occ0' in occstatus:
73569419bafSAndrew Jeffery            occ0 = occstatus["/org/open_power/control/occ0"]['OccActive']
73669419bafSAndrew Jeffery            if occ0 == 1:
73769419bafSAndrew Jeffery                occ0 = 'Active'
73869419bafSAndrew Jeffery            else:
73969419bafSAndrew Jeffery                occ0 = 'Inactive'
74069419bafSAndrew Jeffery            output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
74169419bafSAndrew Jeffery            occ1 = occstatus["/org/open_power/control/occ1"]['OccActive']
74269419bafSAndrew Jeffery            if occ1 == 1:
74369419bafSAndrew Jeffery                occ1 = 'Active'
74469419bafSAndrew Jeffery            else:
74569419bafSAndrew Jeffery                occ1 = 'Inactive'
74669419bafSAndrew Jeffery            output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}
74769419bafSAndrew Jeffery        else:
74869419bafSAndrew Jeffery            output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
74969419bafSAndrew Jeffery            output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}
75069419bafSAndrew Jeffery        keylist = ['sensorName', 'type', 'units', 'value', 'target']
75169419bafSAndrew Jeffery
75269419bafSAndrew Jeffery        return tableDisplay(keylist, colNames, output)
75369419bafSAndrew Jeffery    else:
75469419bafSAndrew Jeffery        return res.text + occres.text
75569419bafSAndrew Jeffery
75669419bafSAndrew Jefferydef sel(host, args, session):
75769419bafSAndrew Jeffery    """
75869419bafSAndrew Jeffery         prints out the bmc alerts
75969419bafSAndrew Jeffery
76069419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
76169419bafSAndrew Jeffery         @param args: contains additional arguments used by the sel sub command
76269419bafSAndrew Jeffery         @param session: the active session to use
76369419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
76469419bafSAndrew Jeffery    """
76569419bafSAndrew Jeffery
76669419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/logging/entry/enumerate"
76769419bafSAndrew Jeffery    try:
76869419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
76969419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
77069419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
77169419bafSAndrew Jeffery    return res.text
77269419bafSAndrew Jeffery
77369419bafSAndrew Jeffery
77469419bafSAndrew Jefferydef parseESEL(args, eselRAW):
77569419bafSAndrew Jeffery    """
77669419bafSAndrew Jeffery         parses the esel data and gets predetermined search terms
77769419bafSAndrew Jeffery
77869419bafSAndrew Jeffery         @param eselRAW: string, the raw esel string from the bmc
77969419bafSAndrew Jeffery         @return: A dictionary containing the quick snapshot data unless args.fullEsel is listed then a full PEL log is returned
78069419bafSAndrew Jeffery    """
78169419bafSAndrew Jeffery    eselParts = {}
78269419bafSAndrew Jeffery    esel_bin = binascii.unhexlify(''.join(eselRAW.split()[16:]))
78369419bafSAndrew Jeffery    #search terms contains the search term as the key and the return dictionary key as it's value
78469419bafSAndrew Jeffery    searchTerms = { 'Signature Description':'signatureDescription', 'devdesc':'devdesc',
78569419bafSAndrew Jeffery                    'Callout type': 'calloutType', 'Procedure':'procedure', 'Sensor Type': 'sensorType'}
78669419bafSAndrew Jeffery    uniqueID = str(uuid.uuid4())
78769419bafSAndrew Jeffery    eselBinPath = tempfile.gettempdir() + os.sep + uniqueID + 'esel.bin'
78869419bafSAndrew Jeffery    with open(eselBinPath, 'wb') as f:
78969419bafSAndrew Jeffery        f.write(esel_bin)
79069419bafSAndrew Jeffery    errlPath = ""
79169419bafSAndrew Jeffery    #use the right errl file for the machine architecture
79269419bafSAndrew Jeffery    arch = platform.machine()
79369419bafSAndrew Jeffery    if(arch =='x86_64' or arch =='AMD64'):
79469419bafSAndrew Jeffery        if os.path.exists('/opt/ibm/ras/bin/x86_64/errl'):
79569419bafSAndrew Jeffery            errlPath = '/opt/ibm/ras/bin/x86_64/errl'
79669419bafSAndrew Jeffery        elif os.path.exists('errl/x86_64/errl'):
79769419bafSAndrew Jeffery            errlPath = 'errl/x86_64/errl'
79869419bafSAndrew Jeffery        else:
79969419bafSAndrew Jeffery            errlPath = 'x86_64/errl'
80069419bafSAndrew Jeffery    elif (platform.machine()=='ppc64le'):
80169419bafSAndrew Jeffery        if os.path.exists('/opt/ibm/ras/bin/ppc64le/errl'):
80269419bafSAndrew Jeffery            errlPath = '/opt/ibm/ras/bin/ppc64le/errl'
80369419bafSAndrew Jeffery        elif os.path.exists('errl/ppc64le/errl'):
80469419bafSAndrew Jeffery            errlPath = 'errl/ppc64le/errl'
80569419bafSAndrew Jeffery        else:
80669419bafSAndrew Jeffery            errlPath = 'ppc64le/errl'
80769419bafSAndrew Jeffery    else:
80869419bafSAndrew Jeffery        print("machine architecture not supported for parsing eSELs")
80969419bafSAndrew Jeffery        return eselParts
81069419bafSAndrew Jeffery
81169419bafSAndrew Jeffery    if(os.path.exists(errlPath)):
81269419bafSAndrew Jeffery        output= subprocess.check_output([errlPath, '-d', '--file='+eselBinPath]).decode('utf-8')
81369419bafSAndrew Jeffery#         output = proc.communicate()[0]
81469419bafSAndrew Jeffery        lines = output.split('\n')
81569419bafSAndrew Jeffery
81669419bafSAndrew Jeffery        if(hasattr(args, 'fullEsel')):
81769419bafSAndrew Jeffery            return output
81869419bafSAndrew Jeffery
81969419bafSAndrew Jeffery        for i in range(0, len(lines)):
82069419bafSAndrew Jeffery            lineParts = lines[i].split(':')
82169419bafSAndrew Jeffery            if(len(lineParts)>1): #ignore multi lines, output formatting lines, and other information
82269419bafSAndrew Jeffery                for term in searchTerms:
82369419bafSAndrew Jeffery                    if(term in lineParts[0]):
82469419bafSAndrew Jeffery                        temp = lines[i][lines[i].find(':')+1:].strip()[:-1].strip()
82569419bafSAndrew Jeffery                        if lines[i+1].find(':') != -1:
82669419bafSAndrew Jeffery                            if (len(lines[i+1].split(':')[0][1:].strip())==0):
82769419bafSAndrew Jeffery                                while(len(lines[i][:lines[i].find(':')].strip())>2):
82869419bafSAndrew Jeffery                                    #has multiple lines, process and update line counter
82969419bafSAndrew Jeffery                                    if((i+1) <= len(lines)):
83069419bafSAndrew Jeffery                                        i+=1
83169419bafSAndrew Jeffery                                    else:
83269419bafSAndrew Jeffery                                        i=i-1
83369419bafSAndrew Jeffery                                        break
83469419bafSAndrew Jeffery                                    #Append the content from the next line removing the pretty display characters
83569419bafSAndrew Jeffery                                    #Finds the first colon then starts 2 characters after, then removes all whitespace
83669419bafSAndrew Jeffery                                    temp = temp + lines[i][lines[i].find(':')+2:].strip()[:-1].strip()[:-1].strip()
83769419bafSAndrew Jeffery                        if(searchTerms[term] in eselParts):
83869419bafSAndrew Jeffery                            eselParts[searchTerms[term]] = eselParts[searchTerms[term]] + ", " + temp
83969419bafSAndrew Jeffery                        else:
84069419bafSAndrew Jeffery                            eselParts[searchTerms[term]] = temp
84169419bafSAndrew Jeffery        os.remove(eselBinPath)
84269419bafSAndrew Jeffery    else:
84369419bafSAndrew Jeffery        print("errl file cannot be found")
84469419bafSAndrew Jeffery
84569419bafSAndrew Jeffery    return eselParts
84669419bafSAndrew Jeffery
84769419bafSAndrew Jeffery
84869419bafSAndrew Jefferydef getESELSeverity(esel):
84969419bafSAndrew Jeffery    """
85069419bafSAndrew Jeffery        Finds the severity type in an eSEL from the User Header section.
85169419bafSAndrew Jeffery        @param esel - the eSEL data
85269419bafSAndrew Jeffery        @return severity - e.g. 'Critical'
85369419bafSAndrew Jeffery    """
85469419bafSAndrew Jeffery
85569419bafSAndrew Jeffery    # everything but 1 and 2 are Critical
85669419bafSAndrew Jeffery    # '1': 'recovered',
85769419bafSAndrew Jeffery    # '2': 'predictive',
85869419bafSAndrew Jeffery    # '4': 'unrecoverable',
85969419bafSAndrew Jeffery    # '5': 'critical',
86069419bafSAndrew Jeffery    # '6': 'diagnostic',
86169419bafSAndrew Jeffery    # '7': 'symptom'
86269419bafSAndrew Jeffery    severities = {
86369419bafSAndrew Jeffery        '1': 'Informational',
86469419bafSAndrew Jeffery        '2': 'Warning'
86569419bafSAndrew Jeffery    }
86669419bafSAndrew Jeffery
86769419bafSAndrew Jeffery    try:
86869419bafSAndrew Jeffery        headerPosition = esel.index('55 48') # 'UH'
86969419bafSAndrew Jeffery        # The severity is the last byte in the 8 byte section (a byte is '  bb')
87069419bafSAndrew Jeffery        severity = esel[headerPosition:headerPosition+32].split(' ')[-1]
87169419bafSAndrew Jeffery        type = severity[0]
87269419bafSAndrew Jeffery    except ValueError:
87369419bafSAndrew Jeffery        print("Could not find severity value in UH section in eSEL")
87469419bafSAndrew Jeffery        type = 'x';
87569419bafSAndrew Jeffery
87669419bafSAndrew Jeffery    return severities.get(type, 'Critical')
87769419bafSAndrew Jeffery
87869419bafSAndrew Jeffery
87969419bafSAndrew Jefferydef sortSELs(events):
88069419bafSAndrew Jeffery    """
88169419bafSAndrew Jeffery         sorts the sels by timestamp, then log entry number
88269419bafSAndrew Jeffery
88369419bafSAndrew Jeffery         @param events: Dictionary containing events
88469419bafSAndrew Jeffery         @return: list containing a list of the ordered log entries, and dictionary of keys
88569419bafSAndrew Jeffery    """
88669419bafSAndrew Jeffery    logNumList = []
88769419bafSAndrew Jeffery    timestampList = []
88869419bafSAndrew Jeffery    eventKeyDict = {}
88969419bafSAndrew Jeffery    eventsWithTimestamp = {}
89069419bafSAndrew Jeffery    logNum2events = {}
89169419bafSAndrew Jeffery    for key in events:
89269419bafSAndrew Jeffery        if key == 'numAlerts': continue
89369419bafSAndrew Jeffery        if 'callout' in key: continue
89469419bafSAndrew Jeffery        timestamp = (events[key]['timestamp'])
89569419bafSAndrew Jeffery        if timestamp not in timestampList:
89669419bafSAndrew Jeffery            eventsWithTimestamp[timestamp] = [events[key]['logNum']]
89769419bafSAndrew Jeffery        else:
89869419bafSAndrew Jeffery            eventsWithTimestamp[timestamp].append(events[key]['logNum'])
89969419bafSAndrew Jeffery        #map logNumbers to the event dictionary keys
90069419bafSAndrew Jeffery        eventKeyDict[str(events[key]['logNum'])] = key
90169419bafSAndrew Jeffery
90269419bafSAndrew Jeffery    timestampList = list(eventsWithTimestamp.keys())
90369419bafSAndrew Jeffery    timestampList.sort()
90469419bafSAndrew Jeffery    for ts in timestampList:
90569419bafSAndrew Jeffery        if len(eventsWithTimestamp[ts]) > 1:
90669419bafSAndrew Jeffery            tmplist = eventsWithTimestamp[ts]
90769419bafSAndrew Jeffery            tmplist.sort()
90869419bafSAndrew Jeffery            logNumList = logNumList + tmplist
90969419bafSAndrew Jeffery        else:
91069419bafSAndrew Jeffery            logNumList = logNumList + eventsWithTimestamp[ts]
91169419bafSAndrew Jeffery
91269419bafSAndrew Jeffery    return [logNumList, eventKeyDict]
91369419bafSAndrew Jeffery
91469419bafSAndrew Jeffery
91569419bafSAndrew Jefferydef parseAlerts(policyTable, selEntries, args):
91669419bafSAndrew Jeffery    """
91769419bafSAndrew Jeffery         parses alerts in the IBM CER format, using an IBM policy Table
91869419bafSAndrew Jeffery
91969419bafSAndrew Jeffery         @param policyTable: dictionary, the policy table entries
92069419bafSAndrew Jeffery         @param selEntries: dictionary, the alerts retrieved from the bmc
92169419bafSAndrew Jeffery         @return: A dictionary of the parsed entries, in chronological order
92269419bafSAndrew Jeffery    """
92369419bafSAndrew Jeffery    eventDict = {}
92469419bafSAndrew Jeffery    eventNum =""
92569419bafSAndrew Jeffery    count = 0
92669419bafSAndrew Jeffery    esel = ""
92769419bafSAndrew Jeffery    eselParts = {}
92869419bafSAndrew Jeffery    i2cdevice= ""
92969419bafSAndrew Jeffery    eselSeverity = None
93069419bafSAndrew Jeffery
93169419bafSAndrew Jeffery    'prepare and sort the event entries'
93269419bafSAndrew Jeffery    sels = {}
93369419bafSAndrew Jeffery    for key in selEntries:
93469419bafSAndrew Jeffery        if '/xyz/openbmc_project/logging/entry/' not in key: continue
93569419bafSAndrew Jeffery        if 'callout' not in key:
93669419bafSAndrew Jeffery            sels[key] = selEntries[key]
93769419bafSAndrew Jeffery            sels[key]['logNum'] = key.split('/')[-1]
93869419bafSAndrew Jeffery            sels[key]['timestamp'] = selEntries[key]['Timestamp']
93969419bafSAndrew Jeffery    sortedEntries = sortSELs(sels)
94069419bafSAndrew Jeffery    logNumList = sortedEntries[0]
94169419bafSAndrew Jeffery    eventKeyDict = sortedEntries[1]
94269419bafSAndrew Jeffery
94369419bafSAndrew Jeffery    for logNum in logNumList:
94469419bafSAndrew Jeffery        key = eventKeyDict[logNum]
94569419bafSAndrew Jeffery        hasEsel=False
94669419bafSAndrew Jeffery        i2creadFail = False
94769419bafSAndrew Jeffery        if 'callout' in key:
94869419bafSAndrew Jeffery            continue
94969419bafSAndrew Jeffery        else:
95069419bafSAndrew Jeffery            messageID = str(selEntries[key]['Message'])
95169419bafSAndrew Jeffery            addDataPiece = selEntries[key]['AdditionalData']
95269419bafSAndrew Jeffery            calloutIndex = 0
95369419bafSAndrew Jeffery            calloutFound = False
95469419bafSAndrew Jeffery            for i in range(len(addDataPiece)):
95569419bafSAndrew Jeffery                if("CALLOUT_INVENTORY_PATH" in addDataPiece[i]):
95669419bafSAndrew Jeffery                    calloutIndex = i
95769419bafSAndrew Jeffery                    calloutFound = True
95869419bafSAndrew Jeffery                    fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
95969419bafSAndrew Jeffery                if("CALLOUT_DEVICE_PATH" in addDataPiece[i]):
96069419bafSAndrew Jeffery                    i2creadFail = True
96169419bafSAndrew Jeffery
96269419bafSAndrew Jeffery                    fruCallout = str(addDataPiece[calloutIndex]).split('=')[1]
96369419bafSAndrew Jeffery
96469419bafSAndrew Jeffery                    # Fall back to "I2C"/"FSI" if dev path isn't in policy table
96569419bafSAndrew Jeffery                    if (messageID + '||' + fruCallout) not in policyTable:
96669419bafSAndrew Jeffery                        i2cdevice = str(addDataPiece[i]).strip().split('=')[1]
96769419bafSAndrew Jeffery                        i2cdevice = '/'.join(i2cdevice.split('/')[-4:])
96869419bafSAndrew Jeffery                        if 'fsi' in str(addDataPiece[calloutIndex]).split('=')[1]:
96969419bafSAndrew Jeffery                            fruCallout = 'FSI'
97069419bafSAndrew Jeffery                        else:
97169419bafSAndrew Jeffery                            fruCallout = 'I2C'
97269419bafSAndrew Jeffery                    calloutFound = True
97369419bafSAndrew Jeffery                if("CALLOUT_GPIO_NUM" in addDataPiece[i]):
97469419bafSAndrew Jeffery                    if not calloutFound:
97569419bafSAndrew Jeffery                        fruCallout = 'GPIO'
97669419bafSAndrew Jeffery                    calloutFound = True
97769419bafSAndrew Jeffery                if("CALLOUT_IIC_BUS" in addDataPiece[i]):
97869419bafSAndrew Jeffery                    if not calloutFound:
97969419bafSAndrew Jeffery                        fruCallout = "I2C"
98069419bafSAndrew Jeffery                    calloutFound = True
98169419bafSAndrew Jeffery                if("CALLOUT_IPMI_SENSOR_NUM" in addDataPiece[i]):
98269419bafSAndrew Jeffery                    if not calloutFound:
98369419bafSAndrew Jeffery                        fruCallout = "IPMI"
98469419bafSAndrew Jeffery                    calloutFound = True
98569419bafSAndrew Jeffery                if("ESEL" in addDataPiece[i]):
98669419bafSAndrew Jeffery                    esel = str(addDataPiece[i]).strip().split('=')[1]
98769419bafSAndrew Jeffery                    eselSeverity = getESELSeverity(esel)
98869419bafSAndrew Jeffery                    if args.devdebug:
98969419bafSAndrew Jeffery                        eselParts = parseESEL(args, esel)
99069419bafSAndrew Jeffery                    hasEsel=True
99169419bafSAndrew Jeffery                if("GPU" in addDataPiece[i]):
99269419bafSAndrew Jeffery                    fruCallout = '/xyz/openbmc_project/inventory/system/chassis/motherboard/gpu' + str(addDataPiece[i]).strip()[-1]
99369419bafSAndrew Jeffery                    calloutFound = True
99469419bafSAndrew Jeffery                if("PROCEDURE" in addDataPiece[i]):
99569419bafSAndrew Jeffery                    fruCallout = str(hex(int(str(addDataPiece[i]).split('=')[1])))[2:]
99669419bafSAndrew Jeffery                    calloutFound = True
99769419bafSAndrew Jeffery                if("RAIL_NAME" in addDataPiece[i]):
99869419bafSAndrew Jeffery                    calloutFound=True
99969419bafSAndrew Jeffery                    fruCallout = str(addDataPiece[i]).split('=')[1].strip()
100069419bafSAndrew Jeffery                if("INPUT_NAME" in addDataPiece[i]):
100169419bafSAndrew Jeffery                    calloutFound=True
100269419bafSAndrew Jeffery                    fruCallout = str(addDataPiece[i]).split('=')[1].strip()
100369419bafSAndrew Jeffery                if("SENSOR_TYPE" in addDataPiece[i]):
100469419bafSAndrew Jeffery                    calloutFound=True
100569419bafSAndrew Jeffery                    fruCallout = str(addDataPiece[i]).split('=')[1].strip()
100669419bafSAndrew Jeffery
100769419bafSAndrew Jeffery            if(calloutFound):
100869419bafSAndrew Jeffery                if fruCallout.strip() != "":
100969419bafSAndrew Jeffery                    policyKey = messageID +"||" +  fruCallout
101069419bafSAndrew Jeffery
101169419bafSAndrew Jeffery                    # Also use the severity for hostboot errors
101269419bafSAndrew Jeffery                    if eselSeverity and messageID == 'org.open_power.Host.Error.Event':
101369419bafSAndrew Jeffery                        policyKey += '||' + eselSeverity
101469419bafSAndrew Jeffery
101569419bafSAndrew Jeffery                        # if not in the table, fall back to the original key
101669419bafSAndrew Jeffery                        if policyKey not in policyTable:
101769419bafSAndrew Jeffery                            policyKey = policyKey.replace('||'+eselSeverity, '')
101869419bafSAndrew Jeffery
101969419bafSAndrew Jeffery                    if policyKey not in policyTable:
102069419bafSAndrew Jeffery                        policyKey = messageID
102169419bafSAndrew Jeffery                else:
102269419bafSAndrew Jeffery                    policyKey = messageID
102369419bafSAndrew Jeffery            else:
102469419bafSAndrew Jeffery                policyKey = messageID
102569419bafSAndrew Jeffery            event = {}
102669419bafSAndrew Jeffery            eventNum = str(count)
102769419bafSAndrew Jeffery            if policyKey in policyTable:
102869419bafSAndrew Jeffery                for pkey in policyTable[policyKey]:
102969419bafSAndrew Jeffery                    if(type(policyTable[policyKey][pkey])== bool):
103069419bafSAndrew Jeffery                        event[pkey] = boolToString(policyTable[policyKey][pkey])
103169419bafSAndrew Jeffery                    else:
103269419bafSAndrew Jeffery                        if (i2creadFail and pkey == 'Message'):
103369419bafSAndrew Jeffery                            event[pkey] = policyTable[policyKey][pkey] + ' ' +i2cdevice
103469419bafSAndrew Jeffery                        else:
103569419bafSAndrew Jeffery                            event[pkey] = policyTable[policyKey][pkey]
103669419bafSAndrew Jeffery                event['timestamp'] = selEntries[key]['Timestamp']
103769419bafSAndrew Jeffery                event['resolved'] = bool(selEntries[key]['Resolved'])
103869419bafSAndrew Jeffery                if(hasEsel):
103969419bafSAndrew Jeffery                    if args.devdebug:
104069419bafSAndrew Jeffery                        event['eselParts'] = eselParts
104169419bafSAndrew Jeffery                    event['raweSEL'] = esel
104269419bafSAndrew Jeffery                event['logNum'] = key.split('/')[-1]
104369419bafSAndrew Jeffery                eventDict['event' + eventNum] = event
104469419bafSAndrew Jeffery
104569419bafSAndrew Jeffery            else:
104669419bafSAndrew Jeffery                severity = str(selEntries[key]['Severity']).split('.')[-1]
104769419bafSAndrew Jeffery                if severity == 'Error':
104869419bafSAndrew Jeffery                    severity = 'Critical'
104969419bafSAndrew Jeffery                eventDict['event'+eventNum] = {}
105069419bafSAndrew Jeffery                eventDict['event' + eventNum]['error'] = "error: Not found in policy table: " + policyKey
105169419bafSAndrew Jeffery                eventDict['event' + eventNum]['timestamp'] = selEntries[key]['Timestamp']
105269419bafSAndrew Jeffery                eventDict['event' + eventNum]['Severity'] = severity
105369419bafSAndrew Jeffery                if(hasEsel):
105469419bafSAndrew Jeffery                    if args.devdebug:
105569419bafSAndrew Jeffery                        eventDict['event' +eventNum]['eselParts'] = eselParts
105669419bafSAndrew Jeffery                    eventDict['event' +eventNum]['raweSEL'] = esel
105769419bafSAndrew Jeffery                eventDict['event' +eventNum]['logNum'] = key.split('/')[-1]
105869419bafSAndrew Jeffery                eventDict['event' +eventNum]['resolved'] = bool(selEntries[key]['Resolved'])
105969419bafSAndrew Jeffery            count += 1
106069419bafSAndrew Jeffery    return eventDict
106169419bafSAndrew Jeffery
106269419bafSAndrew Jeffery
106369419bafSAndrew Jefferydef selDisplay(events, args):
106469419bafSAndrew Jeffery    """
106569419bafSAndrew Jeffery         displays alerts in human readable format
106669419bafSAndrew Jeffery
106769419bafSAndrew Jeffery         @param events: Dictionary containing events
106869419bafSAndrew Jeffery         @return:
106969419bafSAndrew Jeffery    """
107069419bafSAndrew Jeffery    activeAlerts = []
107169419bafSAndrew Jeffery    historyAlerts = []
107269419bafSAndrew Jeffery    sortedEntries = sortSELs(events)
107369419bafSAndrew Jeffery    logNumList = sortedEntries[0]
107469419bafSAndrew Jeffery    eventKeyDict = sortedEntries[1]
107569419bafSAndrew Jeffery    keylist = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message']
107669419bafSAndrew Jeffery    if(args.devdebug):
107769419bafSAndrew Jeffery        colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity','Message',  'eSEL contents']
107869419bafSAndrew Jeffery        keylist.append('eSEL')
107969419bafSAndrew Jeffery    else:
108069419bafSAndrew Jeffery        colNames = ['Entry', 'ID', 'Timestamp', 'Serviceable', 'Severity', 'Message']
108169419bafSAndrew Jeffery    for log in logNumList:
108269419bafSAndrew Jeffery        selDict = {}
108369419bafSAndrew Jeffery        alert = events[eventKeyDict[str(log)]]
108469419bafSAndrew Jeffery        if('error' in alert):
108569419bafSAndrew Jeffery            selDict['Entry'] = alert['logNum']
108669419bafSAndrew Jeffery            selDict['ID'] = 'Unknown'
108769419bafSAndrew Jeffery            selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
108869419bafSAndrew Jeffery            msg = alert['error']
108969419bafSAndrew Jeffery            polMsg = msg.split("policy table:")[0]
109069419bafSAndrew Jeffery            msg = msg.split("policy table:")[1]
109169419bafSAndrew Jeffery            msgPieces = msg.split("||")
109269419bafSAndrew Jeffery            err = msgPieces[0]
109369419bafSAndrew Jeffery            if(err.find("org.open_power.")!=-1):
109469419bafSAndrew Jeffery                err = err.split("org.open_power.")[1]
109569419bafSAndrew Jeffery            elif(err.find("xyz.openbmc_project.")!=-1):
109669419bafSAndrew Jeffery                err = err.split("xyz.openbmc_project.")[1]
109769419bafSAndrew Jeffery            else:
109869419bafSAndrew Jeffery                err = msgPieces[0]
109969419bafSAndrew Jeffery            callout = ""
110069419bafSAndrew Jeffery            if len(msgPieces) >1:
110169419bafSAndrew Jeffery                callout = msgPieces[1]
110269419bafSAndrew Jeffery                if(callout.find("/org/open_power/")!=-1):
110369419bafSAndrew Jeffery                    callout = callout.split("/org/open_power/")[1]
110469419bafSAndrew Jeffery                elif(callout.find("/xyz/openbmc_project/")!=-1):
110569419bafSAndrew Jeffery                    callout = callout.split("/xyz/openbmc_project/")[1]
110669419bafSAndrew Jeffery                else:
110769419bafSAndrew Jeffery                    callout = msgPieces[1]
110869419bafSAndrew Jeffery            selDict['Message'] = polMsg +"policy table: "+ err +  "||" + callout
110969419bafSAndrew Jeffery            selDict['Serviceable'] = 'Unknown'
111069419bafSAndrew Jeffery            selDict['Severity'] = alert['Severity']
111169419bafSAndrew Jeffery        else:
111269419bafSAndrew Jeffery            selDict['Entry'] = alert['logNum']
111369419bafSAndrew Jeffery            selDict['ID'] = alert['CommonEventID']
111469419bafSAndrew Jeffery            selDict['Timestamp'] = datetime.datetime.fromtimestamp(int(alert['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
111569419bafSAndrew Jeffery            selDict['Message'] = alert['Message']
111669419bafSAndrew Jeffery            selDict['Serviceable'] = alert['Serviceable']
111769419bafSAndrew Jeffery            selDict['Severity'] = alert['Severity']
111869419bafSAndrew Jeffery
111969419bafSAndrew Jeffery
112069419bafSAndrew Jeffery        eselOrder = ['refCode','signatureDescription', 'eselType', 'devdesc', 'calloutType', 'procedure']
112169419bafSAndrew Jeffery        if ('eselParts' in alert and args.devdebug):
112269419bafSAndrew Jeffery            eselOutput = ""
112369419bafSAndrew Jeffery            for item in eselOrder:
112469419bafSAndrew Jeffery                if item in alert['eselParts']:
112569419bafSAndrew Jeffery                    eselOutput = eselOutput + item + ": " + alert['eselParts'][item] + " | "
112669419bafSAndrew Jeffery            selDict['eSEL'] = eselOutput
112769419bafSAndrew Jeffery        else:
112869419bafSAndrew Jeffery            if args.devdebug:
112969419bafSAndrew Jeffery                selDict['eSEL'] = "None"
113069419bafSAndrew Jeffery
113169419bafSAndrew Jeffery        if not alert['resolved']:
113269419bafSAndrew Jeffery            activeAlerts.append(selDict)
113369419bafSAndrew Jeffery        else:
113469419bafSAndrew Jeffery            historyAlerts.append(selDict)
113569419bafSAndrew Jeffery    mergedOutput = activeAlerts + historyAlerts
113669419bafSAndrew Jeffery    colWidth = setColWidth(keylist, len(colNames), dict(enumerate(mergedOutput)), colNames)
113769419bafSAndrew Jeffery
113869419bafSAndrew Jeffery    output = ""
113969419bafSAndrew Jeffery    if(len(activeAlerts)>0):
114069419bafSAndrew Jeffery        row = ""
114169419bafSAndrew Jeffery        output +="----Active Alerts----\n"
114269419bafSAndrew Jeffery        for i in range(0, len(colNames)):
114369419bafSAndrew Jeffery            if i!=0: row =row + "| "
114469419bafSAndrew Jeffery            row = row + colNames[i].ljust(colWidth[i])
114569419bafSAndrew Jeffery        output += row + "\n"
114669419bafSAndrew Jeffery
114769419bafSAndrew Jeffery        for i in range(0,len(activeAlerts)):
114869419bafSAndrew Jeffery            row = ""
114969419bafSAndrew Jeffery            for j in range(len(activeAlerts[i])):
115069419bafSAndrew Jeffery                if (j != 0): row = row + "| "
115169419bafSAndrew Jeffery                row = row + activeAlerts[i][keylist[j]].ljust(colWidth[j])
115269419bafSAndrew Jeffery            output += row + "\n"
115369419bafSAndrew Jeffery
115469419bafSAndrew Jeffery    if(len(historyAlerts)>0):
115569419bafSAndrew Jeffery        row = ""
115669419bafSAndrew Jeffery        output+= "----Historical Alerts----\n"
115769419bafSAndrew Jeffery        for i in range(len(colNames)):
115869419bafSAndrew Jeffery            if i!=0: row =row + "| "
115969419bafSAndrew Jeffery            row = row + colNames[i].ljust(colWidth[i])
116069419bafSAndrew Jeffery        output += row + "\n"
116169419bafSAndrew Jeffery
116269419bafSAndrew Jeffery        for i in range(0, len(historyAlerts)):
116369419bafSAndrew Jeffery            row = ""
116469419bafSAndrew Jeffery            for j in range(len(historyAlerts[i])):
116569419bafSAndrew Jeffery                if (j != 0): row = row + "| "
116669419bafSAndrew Jeffery                row = row + historyAlerts[i][keylist[j]].ljust(colWidth[j])
116769419bafSAndrew Jeffery            output += row + "\n"
116869419bafSAndrew Jeffery#         print(events[eventKeyDict[str(log)]])
116969419bafSAndrew Jeffery    return output
117069419bafSAndrew Jeffery
117169419bafSAndrew Jeffery
117269419bafSAndrew Jefferydef selPrint(host, args, session):
117369419bafSAndrew Jeffery    """
117469419bafSAndrew Jeffery         prints out all bmc alerts
117569419bafSAndrew Jeffery
117669419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
117769419bafSAndrew Jeffery         @param args: contains additional arguments used by the fru sub command
117869419bafSAndrew Jeffery         @param session: the active session to use
117969419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
118069419bafSAndrew Jeffery    """
118169419bafSAndrew Jeffery    if(args.policyTableLoc is None):
118269419bafSAndrew Jeffery        if os.path.exists('policyTable.json'):
118369419bafSAndrew Jeffery            ptableLoc = "policyTable.json"
118469419bafSAndrew Jeffery        elif os.path.exists('/opt/ibm/ras/lib/policyTable.json'):
118569419bafSAndrew Jeffery            ptableLoc = '/opt/ibm/ras/lib/policyTable.json'
118669419bafSAndrew Jeffery        else:
118769419bafSAndrew Jeffery            ptableLoc = 'lib/policyTable.json'
118869419bafSAndrew Jeffery    else:
118969419bafSAndrew Jeffery        ptableLoc = args.policyTableLoc
119069419bafSAndrew Jeffery    policyTable = loadPolicyTable(ptableLoc)
119169419bafSAndrew Jeffery    rawselEntries = ""
119269419bafSAndrew Jeffery    if(hasattr(args, 'fileloc') and args.fileloc is not None):
119369419bafSAndrew Jeffery        if os.path.exists(args.fileloc):
119469419bafSAndrew Jeffery            with open(args.fileloc, 'r') as selFile:
119569419bafSAndrew Jeffery                selLines = selFile.readlines()
119669419bafSAndrew Jeffery            rawselEntries = ''.join(selLines)
119769419bafSAndrew Jeffery        else:
119869419bafSAndrew Jeffery            print("Error: File not found")
119969419bafSAndrew Jeffery            sys.exit(1)
120069419bafSAndrew Jeffery    else:
120169419bafSAndrew Jeffery        rawselEntries = sel(host, args, session)
120269419bafSAndrew Jeffery    loadFailed = False
120369419bafSAndrew Jeffery    try:
120469419bafSAndrew Jeffery        selEntries = json.loads(rawselEntries)
120569419bafSAndrew Jeffery    except ValueError:
120669419bafSAndrew Jeffery        loadFailed = True
120769419bafSAndrew Jeffery    if loadFailed:
120869419bafSAndrew Jeffery        cleanSels = json.dumps(rawselEntries).replace('\\n', '')
120969419bafSAndrew Jeffery        #need to load json twice as original content was string escaped a second time
121069419bafSAndrew Jeffery        selEntries = json.loads(json.loads(cleanSels))
121169419bafSAndrew Jeffery    selEntries = selEntries['data']
121269419bafSAndrew Jeffery
121369419bafSAndrew Jeffery    if 'description' in selEntries:
121469419bafSAndrew Jeffery        if(args.json):
121569419bafSAndrew Jeffery            return("{\n\t\"numAlerts\": 0\n}")
121669419bafSAndrew Jeffery        else:
121769419bafSAndrew Jeffery            return("No log entries found")
121869419bafSAndrew Jeffery
121969419bafSAndrew Jeffery    else:
122069419bafSAndrew Jeffery        if(len(policyTable)>0):
122169419bafSAndrew Jeffery            events = parseAlerts(policyTable, selEntries, args)
122269419bafSAndrew Jeffery            if(args.json):
122369419bafSAndrew Jeffery                events["numAlerts"] = len(events)
122469419bafSAndrew Jeffery                retValue = str(json.dumps(events, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
122569419bafSAndrew Jeffery                return retValue
122669419bafSAndrew Jeffery            elif(hasattr(args, 'fullSel')):
122769419bafSAndrew Jeffery                return events
122869419bafSAndrew Jeffery            else:
122969419bafSAndrew Jeffery                #get log numbers to order event entries sequentially
123069419bafSAndrew Jeffery                return selDisplay(events, args)
123169419bafSAndrew Jeffery        else:
123269419bafSAndrew Jeffery            if(args.json):
123369419bafSAndrew Jeffery                return selEntries
123469419bafSAndrew Jeffery            else:
123569419bafSAndrew Jeffery                print("error: Policy Table not found.")
123669419bafSAndrew Jeffery                return selEntries
123769419bafSAndrew Jeffery
123869419bafSAndrew Jefferydef selList(host, args, session):
123969419bafSAndrew Jeffery    """
124069419bafSAndrew Jeffery         prints out all all bmc alerts, or only prints out the specified alerts
124169419bafSAndrew Jeffery
124269419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
124369419bafSAndrew Jeffery         @param args: contains additional arguments used by the fru sub command
124469419bafSAndrew Jeffery         @param session: the active session to use
124569419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
124669419bafSAndrew Jeffery    """
124769419bafSAndrew Jeffery    return(sel(host, args, session))
124869419bafSAndrew Jeffery
124969419bafSAndrew Jeffery
125069419bafSAndrew Jefferydef selClear(host, args, session):
125169419bafSAndrew Jeffery    """
125269419bafSAndrew Jeffery         clears all alerts
125369419bafSAndrew Jeffery
125469419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
125569419bafSAndrew Jeffery         @param args: contains additional arguments used by the fru sub command
125669419bafSAndrew Jeffery         @param session: the active session to use
125769419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
125869419bafSAndrew Jeffery    """
125969419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/logging/action/DeleteAll"
126069419bafSAndrew Jeffery    data = "{\"data\": [] }"
126169419bafSAndrew Jeffery
126269419bafSAndrew Jeffery    try:
126369419bafSAndrew Jeffery        res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
126469419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
126569419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
126669419bafSAndrew Jeffery    if res.status_code == 200:
126769419bafSAndrew Jeffery        return "The Alert Log has been cleared. Please allow a few minutes for the action to complete."
126869419bafSAndrew Jeffery    else:
126969419bafSAndrew Jeffery        print("Unable to clear the logs, trying to clear 1 at a time")
127069419bafSAndrew Jeffery        sels = json.loads(sel(host, args, session))['data']
127169419bafSAndrew Jeffery        for key in sels:
127269419bafSAndrew Jeffery            if 'callout' not in key:
127369419bafSAndrew Jeffery                logNum = key.split('/')[-1]
127469419bafSAndrew Jeffery                url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
127569419bafSAndrew Jeffery                try:
127669419bafSAndrew Jeffery                    session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
127769419bafSAndrew Jeffery                except(requests.exceptions.Timeout):
127869419bafSAndrew Jeffery                    return connectionErrHandler(args.json, "Timeout", None)
127969419bafSAndrew Jeffery                    sys.exit(1)
128069419bafSAndrew Jeffery                except(requests.exceptions.ConnectionError) as err:
128169419bafSAndrew Jeffery                    return connectionErrHandler(args.json, "ConnectionError", err)
128269419bafSAndrew Jeffery                    sys.exit(1)
128369419bafSAndrew Jeffery        return ('Sel clearing complete')
128469419bafSAndrew Jeffery
128569419bafSAndrew Jefferydef selSetResolved(host, args, session):
128669419bafSAndrew Jeffery    """
128769419bafSAndrew Jeffery         sets a sel entry to resolved
128869419bafSAndrew Jeffery
128969419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
129069419bafSAndrew Jeffery         @param args: contains additional arguments used by the fru sub command
129169419bafSAndrew Jeffery         @param session: the active session to use
129269419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
129369419bafSAndrew Jeffery    """
129469419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/logging/entry/" + str(args.selNum) + "/attr/Resolved"
129569419bafSAndrew Jeffery    data = "{\"data\": 1 }"
129669419bafSAndrew Jeffery    try:
129769419bafSAndrew Jeffery        res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
129869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
129969419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
130069419bafSAndrew Jeffery    if res.status_code == 200:
130169419bafSAndrew Jeffery        return "Sel entry "+ str(args.selNum) +" is now set to resolved"
130269419bafSAndrew Jeffery    else:
130369419bafSAndrew Jeffery        return "Unable to set the alert to resolved"
130469419bafSAndrew Jeffery
130569419bafSAndrew Jefferydef selResolveAll(host, args, session):
130669419bafSAndrew Jeffery    """
130769419bafSAndrew Jeffery         sets a sel entry to resolved
130869419bafSAndrew Jeffery
130969419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
131069419bafSAndrew Jeffery         @param args: contains additional arguments used by the fru sub command
131169419bafSAndrew Jeffery         @param session: the active session to use
131269419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
131369419bafSAndrew Jeffery    """
131469419bafSAndrew Jeffery    rawselEntries = sel(host, args, session)
131569419bafSAndrew Jeffery    loadFailed = False
131669419bafSAndrew Jeffery    try:
131769419bafSAndrew Jeffery        selEntries = json.loads(rawselEntries)
131869419bafSAndrew Jeffery    except ValueError:
131969419bafSAndrew Jeffery        loadFailed = True
132069419bafSAndrew Jeffery    if loadFailed:
132169419bafSAndrew Jeffery        cleanSels = json.dumps(rawselEntries).replace('\\n', '')
132269419bafSAndrew Jeffery        #need to load json twice as original content was string escaped a second time
132369419bafSAndrew Jeffery        selEntries = json.loads(json.loads(cleanSels))
132469419bafSAndrew Jeffery    selEntries = selEntries['data']
132569419bafSAndrew Jeffery
132669419bafSAndrew Jeffery    if 'description' in selEntries:
132769419bafSAndrew Jeffery        if(args.json):
132869419bafSAndrew Jeffery            return("{\n\t\"selsResolved\": 0\n}")
132969419bafSAndrew Jeffery        else:
133069419bafSAndrew Jeffery            return("No log entries found")
133169419bafSAndrew Jeffery    else:
133269419bafSAndrew Jeffery        d = vars(args)
133369419bafSAndrew Jeffery        successlist = []
133469419bafSAndrew Jeffery        failedlist = []
133569419bafSAndrew Jeffery        for key in selEntries:
133669419bafSAndrew Jeffery            if 'callout' not in key:
133769419bafSAndrew Jeffery                d['selNum'] = key.split('/')[-1]
133869419bafSAndrew Jeffery                resolved = selSetResolved(host,args,session)
133969419bafSAndrew Jeffery                if 'Sel entry' in resolved:
134069419bafSAndrew Jeffery                    successlist.append(d['selNum'])
134169419bafSAndrew Jeffery                else:
134269419bafSAndrew Jeffery                    failedlist.append(d['selNum'])
134369419bafSAndrew Jeffery        output = ""
134469419bafSAndrew Jeffery        successlist.sort()
134569419bafSAndrew Jeffery        failedlist.sort()
134669419bafSAndrew Jeffery        if len(successlist)>0:
134769419bafSAndrew Jeffery            output = "Successfully resolved: " +', '.join(successlist) +"\n"
134869419bafSAndrew Jeffery        if len(failedlist)>0:
134969419bafSAndrew Jeffery            output += "Failed to resolve: " + ', '.join(failedlist) + "\n"
135069419bafSAndrew Jeffery        return output
135169419bafSAndrew Jeffery
135269419bafSAndrew Jefferydef chassisPower(host, args, session):
135369419bafSAndrew Jeffery    """
135469419bafSAndrew Jeffery         called by the chassis function. Controls the power state of the chassis, or gets the status
135569419bafSAndrew Jeffery
135669419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
135769419bafSAndrew Jeffery         @param args: contains additional arguments used by the fru sub command
135869419bafSAndrew Jeffery         @param session: the active session to use
135969419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
136069419bafSAndrew Jeffery    """
136169419bafSAndrew Jeffery    if(args.powcmd == 'on'):
136269419bafSAndrew Jeffery        if checkFWactivation(host, args, session):
136369419bafSAndrew Jeffery            return ("Chassis Power control disabled during firmware activation")
136469419bafSAndrew Jeffery        print("Attempting to Power on...:")
136569419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
136669419bafSAndrew Jeffery        data = '{"data":"xyz.openbmc_project.State.Host.Transition.On"}'
136769419bafSAndrew Jeffery        try:
136869419bafSAndrew Jeffery            res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
136969419bafSAndrew Jeffery        except(requests.exceptions.Timeout):
137069419bafSAndrew Jeffery            return(connectionErrHandler(args.json, "Timeout", None))
137169419bafSAndrew Jeffery        return res.text
137269419bafSAndrew Jeffery    elif(args.powcmd == 'softoff'):
137369419bafSAndrew Jeffery        if checkFWactivation(host, args, session):
137469419bafSAndrew Jeffery            return ("Chassis Power control disabled during firmware activation")
137569419bafSAndrew Jeffery        print("Attempting to Power off gracefully...:")
137669419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/state/host0/attr/RequestedHostTransition"
137769419bafSAndrew Jeffery        data = '{"data":"xyz.openbmc_project.State.Host.Transition.Off"}'
137869419bafSAndrew Jeffery        try:
137969419bafSAndrew Jeffery            res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
138069419bafSAndrew Jeffery        except(requests.exceptions.Timeout):
138169419bafSAndrew Jeffery            return(connectionErrHandler(args.json, "Timeout", None))
138269419bafSAndrew Jeffery        return res.text
138369419bafSAndrew Jeffery    elif(args.powcmd == 'hardoff'):
138469419bafSAndrew Jeffery        if checkFWactivation(host, args, session):
138569419bafSAndrew Jeffery            return ("Chassis Power control disabled during firmware activation")
138669419bafSAndrew Jeffery        print("Attempting to Power off immediately...:")
138769419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition"
138869419bafSAndrew Jeffery        data = '{"data":"xyz.openbmc_project.State.Chassis.Transition.Off"}'
138969419bafSAndrew Jeffery        try:
139069419bafSAndrew Jeffery            res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
139169419bafSAndrew Jeffery        except(requests.exceptions.Timeout):
139269419bafSAndrew Jeffery            return(connectionErrHandler(args.json, "Timeout", None))
139369419bafSAndrew Jeffery        return res.text
139469419bafSAndrew Jeffery    elif(args.powcmd == 'status'):
139569419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState"
139669419bafSAndrew Jeffery        try:
139769419bafSAndrew Jeffery            res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
139869419bafSAndrew Jeffery        except(requests.exceptions.Timeout):
139969419bafSAndrew Jeffery            return(connectionErrHandler(args.json, "Timeout", None))
140069419bafSAndrew Jeffery        chassisState = json.loads(res.text)['data'].split('.')[-1]
140169419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/state/host0/attr/CurrentHostState"
140269419bafSAndrew Jeffery        try:
140369419bafSAndrew Jeffery            res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
140469419bafSAndrew Jeffery        except(requests.exceptions.Timeout):
140569419bafSAndrew Jeffery            return(connectionErrHandler(args.json, "Timeout", None))
140669419bafSAndrew Jeffery        hostState = json.loads(res.text)['data'].split('.')[-1]
140769419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/CurrentBMCState"
140869419bafSAndrew Jeffery        try:
140969419bafSAndrew Jeffery            res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
141069419bafSAndrew Jeffery        except(requests.exceptions.Timeout):
141169419bafSAndrew Jeffery            return(connectionErrHandler(args.json, "Timeout", None))
141269419bafSAndrew Jeffery        bmcState = json.loads(res.text)['data'].split('.')[-1]
141369419bafSAndrew Jeffery        if(args.json):
141469419bafSAndrew Jeffery            outDict = {"Chassis Power State" : chassisState, "Host Power State" : hostState, "BMC Power State":bmcState}
141569419bafSAndrew Jeffery            return json.dumps(outDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
141669419bafSAndrew Jeffery        else:
141769419bafSAndrew Jeffery            return "Chassis Power State: " +chassisState + "\nHost Power State: " + hostState + "\nBMC Power State: " + bmcState
141869419bafSAndrew Jeffery    else:
141969419bafSAndrew Jeffery        return "Invalid chassis power command"
142069419bafSAndrew Jeffery
142169419bafSAndrew Jeffery
142269419bafSAndrew Jefferydef chassisIdent(host, args, session):
142369419bafSAndrew Jeffery    """
142469419bafSAndrew Jeffery         called by the chassis function. Controls the identify led of the chassis. Sets or gets the state
142569419bafSAndrew Jeffery
142669419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
142769419bafSAndrew Jeffery         @param args: contains additional arguments used by the fru sub command
142869419bafSAndrew Jeffery         @param session: the active session to use
142969419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
143069419bafSAndrew Jeffery    """
143169419bafSAndrew Jeffery    if(args.identcmd == 'on'):
143269419bafSAndrew Jeffery        print("Attempting to turn identify light on...:")
143369419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
143469419bafSAndrew Jeffery        data = '{"data":true}'
143569419bafSAndrew Jeffery        try:
143669419bafSAndrew Jeffery            res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
143769419bafSAndrew Jeffery        except(requests.exceptions.Timeout):
143869419bafSAndrew Jeffery            return(connectionErrHandler(args.json, "Timeout", None))
143969419bafSAndrew Jeffery        return res.text
144069419bafSAndrew Jeffery    elif(args.identcmd == 'off'):
144169419bafSAndrew Jeffery        print("Attempting to turn identify light off...:")
144269419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted"
144369419bafSAndrew Jeffery        data = '{"data":false}'
144469419bafSAndrew Jeffery        try:
144569419bafSAndrew Jeffery            res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
144669419bafSAndrew Jeffery        except(requests.exceptions.Timeout):
144769419bafSAndrew Jeffery            return(connectionErrHandler(args.json, "Timeout", None))
144869419bafSAndrew Jeffery        return res.text
144969419bafSAndrew Jeffery    elif(args.identcmd == 'status'):
145069419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/led/groups/enclosure_identify"
145169419bafSAndrew Jeffery        try:
145269419bafSAndrew Jeffery            res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
145369419bafSAndrew Jeffery        except(requests.exceptions.Timeout):
145469419bafSAndrew Jeffery            return(connectionErrHandler(args.json, "Timeout", None))
145569419bafSAndrew Jeffery        status = json.loads(res.text)['data']
145669419bafSAndrew Jeffery        if(args.json):
145769419bafSAndrew Jeffery            return status
145869419bafSAndrew Jeffery        else:
145969419bafSAndrew Jeffery            if status['Asserted'] == 0:
146069419bafSAndrew Jeffery                return "Identify light is off"
146169419bafSAndrew Jeffery            else:
146269419bafSAndrew Jeffery                return "Identify light is blinking"
146369419bafSAndrew Jeffery    else:
146469419bafSAndrew Jeffery        return "Invalid chassis identify command"
146569419bafSAndrew Jeffery
146669419bafSAndrew Jeffery
146769419bafSAndrew Jefferydef chassis(host, args, session):
146869419bafSAndrew Jeffery    """
146969419bafSAndrew Jeffery         controls the different chassis commands
147069419bafSAndrew Jeffery
147169419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
147269419bafSAndrew Jeffery         @param args: contains additional arguments used by the fru sub command
147369419bafSAndrew Jeffery         @param session: the active session to use
147469419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
147569419bafSAndrew Jeffery    """
147669419bafSAndrew Jeffery    if(hasattr(args, 'powcmd')):
147769419bafSAndrew Jeffery        result = chassisPower(host,args,session)
147869419bafSAndrew Jeffery    elif(hasattr(args, 'identcmd')):
147969419bafSAndrew Jeffery        result = chassisIdent(host, args, session)
148069419bafSAndrew Jeffery    else:
148169419bafSAndrew Jeffery        return "This feature is not yet implemented"
148269419bafSAndrew Jeffery    return result
148369419bafSAndrew Jeffery
14844e178110SAsmitha Karunanithidef getTask(host, args, session):
14854e178110SAsmitha Karunanithi    """
14864e178110SAsmitha Karunanithi         Get operation on the Task Monitor URI
14874e178110SAsmitha Karunanithi
14884e178110SAsmitha Karunanithi         @param host: string, the hostname or IP address of the bmc
14894e178110SAsmitha Karunanithi         @param args: contains additional arguments used by the task sub command
14904e178110SAsmitha Karunanithi         @param session: the active session to use
14914e178110SAsmitha Karunanithi         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
14924e178110SAsmitha Karunanithi    """
14934e178110SAsmitha Karunanithi    if args.taskURI is not None:
14944e178110SAsmitha Karunanithi        url ='https://'+host+str(args.taskURI)
14954e178110SAsmitha Karunanithi        try:
14964e178110SAsmitha Karunanithi            r = session.post(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
14974e178110SAsmitha Karunanithi            if (r.status_code == 200 and not args.json):
14984e178110SAsmitha Karunanithi                return r.text
14994e178110SAsmitha Karunanithi            elif (r.status_code == 200 and args.json):
15004e178110SAsmitha Karunanithi                return r.json()
15014e178110SAsmitha Karunanithi            else:
15024e178110SAsmitha Karunanithi                return ('Failed to retrieve the data on Task Monitor URI')
15034e178110SAsmitha Karunanithi        except(requests.exceptions.Timeout):
15044e178110SAsmitha Karunanithi            return connectionErrHandler(args.json, "Timeout", None)
15054e178110SAsmitha Karunanithi        except(requests.exceptions.ConnectionError) as err:
15064e178110SAsmitha Karunanithi            return connectionErrHandler(args.json, "ConnectionError", err)
15074e178110SAsmitha Karunanithi    else:
15084e178110SAsmitha Karunanithi        return 'You must specify the Task Monitor URI'
15094e178110SAsmitha Karunanithi
15104e178110SAsmitha Karunanithi
151169419bafSAndrew Jefferydef dumpRetrieve(host, args, session):
151269419bafSAndrew Jeffery    """
151369419bafSAndrew Jeffery         Downloads dump of given dump type
151469419bafSAndrew Jeffery
151569419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
151669419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
151769419bafSAndrew Jeffery         @param session: the active session to use
151869419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
151969419bafSAndrew Jeffery    """
152069419bafSAndrew Jeffery    dumpType = args.dumpType
152169419bafSAndrew Jeffery    if (args.dumpType=="SystemDump"):
152269419bafSAndrew Jeffery        dumpResp=systemDumpRetrieve(host,args,session)
152369419bafSAndrew Jeffery    elif(args.dumpType=="bmc"):
152469419bafSAndrew Jeffery        dumpResp=bmcDumpRetrieve(host,args,session)
152569419bafSAndrew Jeffery    return dumpResp
152669419bafSAndrew Jeffery
152769419bafSAndrew Jefferydef dumpList(host, args, session):
152869419bafSAndrew Jeffery    """
152969419bafSAndrew Jeffery         Lists dump of the given dump type
153069419bafSAndrew Jeffery
153169419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
153269419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
153369419bafSAndrew Jeffery         @param session: the active session to use
153469419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
153569419bafSAndrew Jeffery    """
153669419bafSAndrew Jeffery    if (args.dumpType=="SystemDump"):
153769419bafSAndrew Jeffery        dumpResp=systemDumpList(host,args,session)
153869419bafSAndrew Jeffery    elif(args.dumpType=="bmc"):
153969419bafSAndrew Jeffery        dumpResp=bmcDumpList(host,args,session)
154069419bafSAndrew Jeffery    return dumpResp
154169419bafSAndrew Jeffery
154269419bafSAndrew Jefferydef dumpDelete(host, args, session):
154369419bafSAndrew Jeffery    """
154469419bafSAndrew Jeffery         Deletes dump of the given dump type
154569419bafSAndrew Jeffery
154669419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
154769419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
154869419bafSAndrew Jeffery         @param session: the active session to use
154969419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
155069419bafSAndrew Jeffery    """
155169419bafSAndrew Jeffery    if (args.dumpType=="SystemDump"):
155269419bafSAndrew Jeffery        dumpResp=systemDumpDelete(host,args,session)
155369419bafSAndrew Jeffery    elif(args.dumpType=="bmc"):
155469419bafSAndrew Jeffery        dumpResp=bmcDumpDelete(host,args,session)
155569419bafSAndrew Jeffery    return dumpResp
155669419bafSAndrew Jeffery
155769419bafSAndrew Jefferydef dumpDeleteAll(host, args, session):
155869419bafSAndrew Jeffery    """
155969419bafSAndrew Jeffery         Deletes all dumps of the given dump type
156069419bafSAndrew Jeffery
156169419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
156269419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
156369419bafSAndrew Jeffery         @param session: the active session to use
156469419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
156569419bafSAndrew Jeffery    """
156669419bafSAndrew Jeffery    if (args.dumpType=="SystemDump"):
156769419bafSAndrew Jeffery        dumpResp=systemDumpDeleteAll(host,args,session)
156869419bafSAndrew Jeffery    elif(args.dumpType=="bmc"):
156969419bafSAndrew Jeffery        dumpResp=bmcDumpDeleteAll(host,args,session)
157069419bafSAndrew Jeffery    return dumpResp
157169419bafSAndrew Jeffery
157269419bafSAndrew Jefferydef dumpCreate(host, args, session):
157369419bafSAndrew Jeffery    """
157469419bafSAndrew Jeffery         Creates dump for the given dump type
157569419bafSAndrew Jeffery
157669419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
157769419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
157869419bafSAndrew Jeffery         @param session: the active session to use
157969419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
158069419bafSAndrew Jeffery    """
158169419bafSAndrew Jeffery    if (args.dumpType=="SystemDump"):
158269419bafSAndrew Jeffery        dumpResp=systemDumpCreate(host,args,session)
158369419bafSAndrew Jeffery    elif(args.dumpType=="bmc"):
158469419bafSAndrew Jeffery        dumpResp=bmcDumpCreate(host,args,session)
158569419bafSAndrew Jeffery    return dumpResp
158669419bafSAndrew Jeffery
158769419bafSAndrew Jeffery
158869419bafSAndrew Jefferydef bmcDumpRetrieve(host, args, session):
158969419bafSAndrew Jeffery    """
159069419bafSAndrew Jeffery         Downloads a dump file from the bmc
159169419bafSAndrew Jeffery
159269419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
159369419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
159469419bafSAndrew Jeffery         @param session: the active session to use
159569419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
159669419bafSAndrew Jeffery    """
159769419bafSAndrew Jeffery    dumpNum = args.dumpNum
159869419bafSAndrew Jeffery    if (args.dumpSaveLoc is not None):
159969419bafSAndrew Jeffery        saveLoc = args.dumpSaveLoc
160069419bafSAndrew Jeffery    else:
160169419bafSAndrew Jeffery        saveLoc = tempfile.gettempdir()
160269419bafSAndrew Jeffery    url ='https://'+host+'/download/dump/' + str(dumpNum)
160369419bafSAndrew Jeffery    try:
160469419bafSAndrew Jeffery        r = session.get(url, headers=jsonHeader, stream=True, verify=False, timeout=baseTimeout)
160569419bafSAndrew Jeffery        if (args.dumpSaveLoc is not None):
160669419bafSAndrew Jeffery            if os.path.exists(saveLoc):
160769419bafSAndrew Jeffery                if saveLoc[-1] != os.path.sep:
160869419bafSAndrew Jeffery                    saveLoc = saveLoc + os.path.sep
160969419bafSAndrew Jeffery                filename = saveLoc + host+'-dump' + str(dumpNum) + '.tar.xz'
161069419bafSAndrew Jeffery
161169419bafSAndrew Jeffery            else:
161269419bafSAndrew Jeffery                return 'Invalid save location specified'
161369419bafSAndrew Jeffery        else:
161469419bafSAndrew Jeffery            filename = tempfile.gettempdir()+os.sep + host+'-dump' + str(dumpNum) + '.tar.xz'
161569419bafSAndrew Jeffery
161669419bafSAndrew Jeffery        with open(filename, 'wb') as f:
161769419bafSAndrew Jeffery                    for chunk in r.iter_content(chunk_size =1024):
161869419bafSAndrew Jeffery                        if chunk:
161969419bafSAndrew Jeffery                            f.write(chunk)
162069419bafSAndrew Jeffery        return 'Saved as ' + filename
162169419bafSAndrew Jeffery
162269419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
162369419bafSAndrew Jeffery        return connectionErrHandler(args.json, "Timeout", None)
162469419bafSAndrew Jeffery
162569419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
162669419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
162769419bafSAndrew Jeffery
162869419bafSAndrew Jefferydef bmcDumpList(host, args, session):
162969419bafSAndrew Jeffery    """
163069419bafSAndrew Jeffery         Lists the number of dump files on the bmc
163169419bafSAndrew Jeffery
163269419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
163369419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
163469419bafSAndrew Jeffery         @param session: the active session to use
163569419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
163669419bafSAndrew Jeffery    """
163769419bafSAndrew Jeffery    url ='https://'+host+'/xyz/openbmc_project/dump/list'
163869419bafSAndrew Jeffery    try:
163969419bafSAndrew Jeffery        r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
164069419bafSAndrew Jeffery        dumpList = r.json()
164169419bafSAndrew Jeffery        formattedList = []
164269419bafSAndrew Jeffery        #remove items that aren't dump entries 'entry, internal, manager endpoints'
164369419bafSAndrew Jeffery        if 'data' in dumpList:
164469419bafSAndrew Jeffery            for entry in dumpList['data']:
164569419bafSAndrew Jeffery                if 'entry' in entry:
164669419bafSAndrew Jeffery                    if entry.split('/')[-1].isnumeric():
164769419bafSAndrew Jeffery                        formattedList.append(entry)
164869419bafSAndrew Jeffery            dumpList['data']= formattedList
164969419bafSAndrew Jeffery        return dumpList
165069419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
165169419bafSAndrew Jeffery        return connectionErrHandler(args.json, "Timeout", None)
165269419bafSAndrew Jeffery
165369419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
165469419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
165569419bafSAndrew Jeffery
165669419bafSAndrew Jefferydef bmcDumpDelete(host, args, session):
165769419bafSAndrew Jeffery    """
165869419bafSAndrew Jeffery         Deletes BMC dump files from the bmc
165969419bafSAndrew Jeffery
166069419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
166169419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
166269419bafSAndrew Jeffery         @param session: the active session to use
166369419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
166469419bafSAndrew Jeffery    """
166569419bafSAndrew Jeffery    dumpList = []
166669419bafSAndrew Jeffery    successList = []
166769419bafSAndrew Jeffery    failedList = []
166869419bafSAndrew Jeffery    if args.dumpNum is not None:
166969419bafSAndrew Jeffery        if isinstance(args.dumpNum, list):
167069419bafSAndrew Jeffery            dumpList = args.dumpNum
167169419bafSAndrew Jeffery        else:
167269419bafSAndrew Jeffery            dumpList.append(args.dumpNum)
167369419bafSAndrew Jeffery        for dumpNum in dumpList:
167469419bafSAndrew Jeffery            url ='https://'+host+'/xyz/openbmc_project/dump/entry/'+str(dumpNum)+'/action/Delete'
167569419bafSAndrew Jeffery            try:
167669419bafSAndrew Jeffery                r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
167769419bafSAndrew Jeffery                if r.status_code == 200:
167869419bafSAndrew Jeffery                    successList.append(str(dumpNum))
167969419bafSAndrew Jeffery                else:
168069419bafSAndrew Jeffery                    failedList.append(str(dumpNum))
168169419bafSAndrew Jeffery            except(requests.exceptions.Timeout):
168269419bafSAndrew Jeffery                return connectionErrHandler(args.json, "Timeout", None)
168369419bafSAndrew Jeffery            except(requests.exceptions.ConnectionError) as err:
168469419bafSAndrew Jeffery                return connectionErrHandler(args.json, "ConnectionError", err)
168569419bafSAndrew Jeffery        output = "Successfully deleted dumps: " + ', '.join(successList)
168669419bafSAndrew Jeffery        if(len(failedList)>0):
168769419bafSAndrew Jeffery            output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
168869419bafSAndrew Jeffery        return output
168969419bafSAndrew Jeffery    else:
169069419bafSAndrew Jeffery        return 'You must specify an entry number to delete'
169169419bafSAndrew Jeffery
169269419bafSAndrew Jefferydef bmcDumpDeleteAll(host, args, session):
169369419bafSAndrew Jeffery    """
169469419bafSAndrew Jeffery         Deletes All BMC dump files from the bmc
169569419bafSAndrew Jeffery
169669419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
169769419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
169869419bafSAndrew Jeffery         @param session: the active session to use
169969419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
170069419bafSAndrew Jeffery    """
170169419bafSAndrew Jeffery    dumpResp = bmcDumpList(host, args, session)
170269419bafSAndrew Jeffery    if 'FQPSPIN0000M' in dumpResp or 'FQPSPIN0001M'in dumpResp:
170369419bafSAndrew Jeffery        return dumpResp
170469419bafSAndrew Jeffery    dumpList = dumpResp['data']
170569419bafSAndrew Jeffery    d = vars(args)
170669419bafSAndrew Jeffery    dumpNums = []
170769419bafSAndrew Jeffery    for dump in dumpList:
170869419bafSAndrew Jeffery        dumpNum = dump.strip().split('/')[-1]
170969419bafSAndrew Jeffery        if dumpNum.isdigit():
171069419bafSAndrew Jeffery            dumpNums.append(int(dumpNum))
171169419bafSAndrew Jeffery    d['dumpNum'] = dumpNums
171269419bafSAndrew Jeffery
171369419bafSAndrew Jeffery    return bmcDumpDelete(host, args, session)
171469419bafSAndrew Jeffery
171569419bafSAndrew Jeffery
171669419bafSAndrew Jefferydef bmcDumpCreate(host, args, session):
171769419bafSAndrew Jeffery    """
171869419bafSAndrew Jeffery         Creates a bmc dump file
171969419bafSAndrew Jeffery
172069419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
172169419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
172269419bafSAndrew Jeffery         @param session: the active session to use
172369419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
172469419bafSAndrew Jeffery    """
172569419bafSAndrew Jeffery    url = 'https://'+host+'/xyz/openbmc_project/dump/action/CreateDump'
172669419bafSAndrew Jeffery    try:
172769419bafSAndrew Jeffery        r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
172869419bafSAndrew Jeffery        info = r.json()
172969419bafSAndrew Jeffery        if(r.status_code == 200 and not args.json):
173069419bafSAndrew Jeffery            return ('Dump successfully created')
173169419bafSAndrew Jeffery        elif(args.json):
173269419bafSAndrew Jeffery            return info
173369419bafSAndrew Jeffery        elif 'data' in info:
173469419bafSAndrew Jeffery            if 'QuotaExceeded' in info['data']['description']:
173569419bafSAndrew Jeffery                return 'BMC dump space is full. Please delete at least one existing dump entry and try again.'
173669419bafSAndrew Jeffery            else:
173769419bafSAndrew Jeffery                return "Failed to create a BMC dump. BMC Response:\n {resp}".format(resp=info)
173869419bafSAndrew Jeffery        else:
173969419bafSAndrew Jeffery            return "Failed to create a BMC dump. BMC Response:\n {resp}".format(resp=info)
174069419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
174169419bafSAndrew Jeffery        return connectionErrHandler(args.json, "Timeout", None)
174269419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
174369419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
174469419bafSAndrew Jeffery
174569419bafSAndrew Jeffery
174669419bafSAndrew Jefferydef systemDumpRetrieve(host, args, session):
174769419bafSAndrew Jeffery    """
174869419bafSAndrew Jeffery         Downloads system dump
174969419bafSAndrew Jeffery
175069419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
175169419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
175269419bafSAndrew Jeffery         @param session: the active session to use
175369419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
175469419bafSAndrew Jeffery    """
175569419bafSAndrew Jeffery    NBDSetup(host,args,session)
175669419bafSAndrew Jeffery    pipe = NBDPipe()
175769419bafSAndrew Jeffery    pipe.openHTTPSocket(args)
175869419bafSAndrew Jeffery    pipe.openTCPSocket()
175969419bafSAndrew Jeffery    pipe.waitformessage()
176069419bafSAndrew Jeffery
176169419bafSAndrew Jefferydef systemDumpList(host, args, session):
176269419bafSAndrew Jeffery    """
176369419bafSAndrew Jeffery         Lists system dumps
176469419bafSAndrew Jeffery
176569419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
176669419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
176769419bafSAndrew Jeffery         @param session: the active session to use
176869419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
176969419bafSAndrew Jeffery    """
177069419bafSAndrew Jeffery    url = "https://"+host+"/redfish/v1/Systems/system/LogServices/Dump/Entries"
177169419bafSAndrew Jeffery    try:
177269419bafSAndrew Jeffery        r = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
177369419bafSAndrew Jeffery        dumpList = r.json()
177469419bafSAndrew Jeffery        return dumpList
177569419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
177669419bafSAndrew Jeffery        return connectionErrHandler(args.json, "Timeout", None)
177769419bafSAndrew Jeffery
177869419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
177969419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
178069419bafSAndrew Jeffery
178169419bafSAndrew Jeffery
178269419bafSAndrew Jefferydef systemDumpDelete(host, args, session):
178369419bafSAndrew Jeffery    """
178469419bafSAndrew Jeffery         Deletes system dump
178569419bafSAndrew Jeffery
178669419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
178769419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
178869419bafSAndrew Jeffery         @param session: the active session to use
178969419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
179069419bafSAndrew Jeffery    """
179169419bafSAndrew Jeffery    dumpList = []
179269419bafSAndrew Jeffery    successList = []
179369419bafSAndrew Jeffery    failedList = []
179469419bafSAndrew Jeffery    if args.dumpNum is not None:
179569419bafSAndrew Jeffery        if isinstance(args.dumpNum, list):
179669419bafSAndrew Jeffery            dumpList = args.dumpNum
179769419bafSAndrew Jeffery        else:
179869419bafSAndrew Jeffery            dumpList.append(args.dumpNum)
179969419bafSAndrew Jeffery        for dumpNum in dumpList:
180069419bafSAndrew Jeffery            url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/Dump/Entries/'+ str(dumpNum)
180169419bafSAndrew Jeffery            try:
180269419bafSAndrew Jeffery                r = session.delete(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
180369419bafSAndrew Jeffery                if r.status_code == 200:
180469419bafSAndrew Jeffery                    successList.append(str(dumpNum))
180569419bafSAndrew Jeffery                else:
180669419bafSAndrew Jeffery                    failedList.append(str(dumpNum))
180769419bafSAndrew Jeffery            except(requests.exceptions.Timeout):
180869419bafSAndrew Jeffery                return connectionErrHandler(args.json, "Timeout", None)
180969419bafSAndrew Jeffery            except(requests.exceptions.ConnectionError) as err:
181069419bafSAndrew Jeffery                return connectionErrHandler(args.json, "ConnectionError", err)
181169419bafSAndrew Jeffery        output = "Successfully deleted dumps: " + ', '.join(successList)
181269419bafSAndrew Jeffery        if(len(failedList)>0):
181369419bafSAndrew Jeffery            output+= '\nFailed to delete dumps: ' + ', '.join(failedList)
181469419bafSAndrew Jeffery        return output
181569419bafSAndrew Jeffery    else:
181669419bafSAndrew Jeffery        return 'You must specify an entry number to delete'
181769419bafSAndrew Jeffery
181869419bafSAndrew Jefferydef systemDumpDeleteAll(host, args, session):
181969419bafSAndrew Jeffery    """
182069419bafSAndrew Jeffery         Deletes All system dumps
182169419bafSAndrew Jeffery
182269419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
182369419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
182469419bafSAndrew Jeffery         @param session: the active session to use
182569419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
182669419bafSAndrew Jeffery    """
182769419bafSAndrew Jeffery    url = 'https://'+host+'/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.ClearLog'
182869419bafSAndrew Jeffery    try:
182969419bafSAndrew Jeffery        r = session.post(url, headers=jsonHeader, json = {"data": []}, verify=False, timeout=baseTimeout)
183069419bafSAndrew Jeffery        if(r.status_code == 200 and not args.json):
183169419bafSAndrew Jeffery            return ('Dumps successfully cleared')
183269419bafSAndrew Jeffery        elif(args.json):
183369419bafSAndrew Jeffery            return r.json()
183469419bafSAndrew Jeffery        else:
183569419bafSAndrew Jeffery            return ('Failed to clear dumps')
183669419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
183769419bafSAndrew Jeffery        return connectionErrHandler(args.json, "Timeout", None)
183869419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
183969419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
184069419bafSAndrew Jeffery
184169419bafSAndrew Jefferydef systemDumpCreate(host, args, session):
184269419bafSAndrew Jeffery    """
184369419bafSAndrew Jeffery         Creates a system dump
184469419bafSAndrew Jeffery
184569419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
184669419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
184769419bafSAndrew Jeffery         @param session: the active session to use
184869419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
184969419bafSAndrew Jeffery    """
18504e178110SAsmitha Karunanithi    url =  'https://'+host+'/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.CollectDiagnosticData'
18514e178110SAsmitha Karunanithi    params = {'DiagnosticDataType':'OEM', 'OEMDiagnosticDataType':'System'}
185269419bafSAndrew Jeffery    try:
18534e178110SAsmitha Karunanithi        r = session.post(url, headers=jsonHeader, params=params, data = json.dumps(params), verify=False, timeout=baseTimeout)
185469419bafSAndrew Jeffery        if(r.status_code == 200):
185569419bafSAndrew Jeffery            return r.json()
185669419bafSAndrew Jeffery        else:
185769419bafSAndrew Jeffery            return ('Failed to create dump')
185869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
185969419bafSAndrew Jeffery        return connectionErrHandler(args.json, "Timeout", None)
186069419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
186169419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
186269419bafSAndrew Jeffery
186369419bafSAndrew Jefferydef csdDumpInitiate(host, args, session):
186469419bafSAndrew Jeffery    """
186569419bafSAndrew Jeffery        Starts the process of getting the current list of dumps then initiates the creation of one.
186669419bafSAndrew Jeffery
186769419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
186869419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
186969419bafSAndrew Jeffery         @param session: the active session to use
187069419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
187169419bafSAndrew Jeffery    """
187269419bafSAndrew Jeffery    errorInfo = ""
187369419bafSAndrew Jeffery    dumpcount = 0
187469419bafSAndrew Jeffery    try:
187569419bafSAndrew Jeffery        d = vars(args)
187669419bafSAndrew Jeffery        d['json'] = True
187769419bafSAndrew Jeffery    except Exception as e:
187869419bafSAndrew Jeffery        errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
187969419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
188069419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
188169419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
188269419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
188369419bafSAndrew Jeffery
188469419bafSAndrew Jeffery    try:
188569419bafSAndrew Jeffery        for i in range(3):
188669419bafSAndrew Jeffery            dumpInfo = bmcDumpList(host, args, session)
188769419bafSAndrew Jeffery            if 'data' in dumpInfo:
188869419bafSAndrew Jeffery                dumpcount = len(dumpInfo['data'])
188969419bafSAndrew Jeffery                break
189069419bafSAndrew Jeffery            else:
189169419bafSAndrew Jeffery                errorInfo+= "Dump List Message returned: " + json.dumps(dumpInfo,indent=0, separators=(',', ':')).replace('\n','') +"\n"
189269419bafSAndrew Jeffery    except Exception as e:
189369419bafSAndrew Jeffery        errorInfo+= "Failed to collect the list of dumps.\nException: {eInfo}\n".format(eInfo=e)
189469419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
189569419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
189669419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
189769419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
189869419bafSAndrew Jeffery
189969419bafSAndrew Jeffery    #Create a user initiated dump
190069419bafSAndrew Jeffery    dumpFailure = True
190169419bafSAndrew Jeffery    try:
190269419bafSAndrew Jeffery        for i in range(3):
190369419bafSAndrew Jeffery            dumpcreated = bmcDumpCreate(host, args, session)
190469419bafSAndrew Jeffery            if 'message' in dumpcreated:
190569419bafSAndrew Jeffery                if 'ok' in dumpcreated['message'].lower():
190669419bafSAndrew Jeffery                    dumpFailure = False
190769419bafSAndrew Jeffery                    break
190869419bafSAndrew Jeffery                elif 'data' in dumpcreated:
190969419bafSAndrew Jeffery                    if 'QuotaExceeded' in dumpcreated['data']['description']:
191069419bafSAndrew Jeffery                        print('Not enough dump space on the BMC to create a new dump. Please delete the oldest entry (lowest number) and rerun the collect_service_data command.')
191169419bafSAndrew Jeffery                        errorInfo+='Dump Space is full. No new dump was created with this collection'
191269419bafSAndrew Jeffery                        break
191369419bafSAndrew Jeffery                    else:
191469419bafSAndrew Jeffery                        errorInfo+= "Dump create message returned: " + json.dumps(dumpcreated,indent=0, separators=(',', ':')).replace('\n','') +"\n"
191569419bafSAndrew Jeffery                else:
191669419bafSAndrew Jeffery                    errorInfo+= "Dump create message returned: " + json.dumps(dumpcreated,indent=0, separators=(',', ':')).replace('\n','') +"\n"
191769419bafSAndrew Jeffery            else:
191869419bafSAndrew Jeffery                errorInfo+= "Dump create message returned: " + json.dumps(dumpcreated,indent=0, separators=(',', ':')).replace('\n','') +"\n"
191969419bafSAndrew Jeffery    except Exception as e:
192069419bafSAndrew Jeffery        errorInfo+= "Dump create exception encountered: {eInfo}\n".format(eInfo=e)
192169419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
192269419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
192369419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
192469419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
192569419bafSAndrew Jeffery
192669419bafSAndrew Jeffery    output = {}
192769419bafSAndrew Jeffery    output['errors'] = errorInfo
192869419bafSAndrew Jeffery    output['dumpcount'] = dumpcount
192969419bafSAndrew Jeffery    if dumpFailure: output['dumpFailure'] = True
193069419bafSAndrew Jeffery    return output
193169419bafSAndrew Jeffery
193269419bafSAndrew Jefferydef csdInventory(host, args,session, fileDir):
193369419bafSAndrew Jeffery    """
193469419bafSAndrew Jeffery        Collects the BMC inventory, retrying if necessary
193569419bafSAndrew Jeffery
193669419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
193769419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
193869419bafSAndrew Jeffery         @param session: the active session to use
193969419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
194069419bafSAndrew Jeffery         @param fileDir: string representation of the path to use for putting files created
194169419bafSAndrew Jeffery    """
194269419bafSAndrew Jeffery    errorInfo = "===========Inventory =============\n"
194369419bafSAndrew Jeffery    output={}
194469419bafSAndrew Jeffery    inventoryCollected = False
194569419bafSAndrew Jeffery    try:
194669419bafSAndrew Jeffery        for i in range(3):
194769419bafSAndrew Jeffery            frulist = fruPrint(host, args, session)
194869419bafSAndrew Jeffery            if 'Hardware' in frulist:
194969419bafSAndrew Jeffery                inventoryCollected = True
195069419bafSAndrew Jeffery                break
195169419bafSAndrew Jeffery            else:
195269419bafSAndrew Jeffery                errorInfo += json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
195369419bafSAndrew Jeffery    except Exception as e:
195469419bafSAndrew Jeffery        errorInfo += "Inventory collection exception: {eInfo}\n".format(eInfo=e)
195569419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
195669419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
195769419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
195869419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
195969419bafSAndrew Jeffery    if inventoryCollected:
196069419bafSAndrew Jeffery        try:
196169419bafSAndrew Jeffery            with open(fileDir +os.sep+'inventory.txt', 'w') as f:
196269419bafSAndrew Jeffery                f.write(json.dumps(frulist, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
196369419bafSAndrew Jeffery            print("Inventory collected and stored in " + fileDir + os.sep + "inventory.txt")
196469419bafSAndrew Jeffery            output['fileLoc'] = fileDir+os.sep+'inventory.txt'
196569419bafSAndrew Jeffery        except Exception as e:
196669419bafSAndrew Jeffery            print("Failed to write inventory to file.")
196769419bafSAndrew Jeffery            errorInfo += "Error writing inventory to the file. Exception: {eInfo}\n".format(eInfo=e)
196869419bafSAndrew Jeffery            exc_type, exc_obj, exc_tb = sys.exc_info()
196969419bafSAndrew Jeffery            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
197069419bafSAndrew Jeffery            errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
197169419bafSAndrew Jeffery            errorInfo += traceback.format_exc()
197269419bafSAndrew Jeffery
197369419bafSAndrew Jeffery    output['errors'] = errorInfo
197469419bafSAndrew Jeffery
197569419bafSAndrew Jeffery    return output
197669419bafSAndrew Jeffery
197769419bafSAndrew Jefferydef csdSensors(host, args,session, fileDir):
197869419bafSAndrew Jeffery    """
197969419bafSAndrew Jeffery        Collects the BMC sensor readings, retrying if necessary
198069419bafSAndrew Jeffery
198169419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
198269419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
198369419bafSAndrew Jeffery         @param session: the active session to use
198469419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
198569419bafSAndrew Jeffery         @param fileDir: string representation of the path to use for putting files created
198669419bafSAndrew Jeffery    """
198769419bafSAndrew Jeffery    errorInfo = "===========Sensors =============\n"
198869419bafSAndrew Jeffery    sensorsCollected = False
198969419bafSAndrew Jeffery    output={}
199069419bafSAndrew Jeffery    try:
199169419bafSAndrew Jeffery        d = vars(args)
199269419bafSAndrew Jeffery        d['json'] = False
199369419bafSAndrew Jeffery    except Exception as e:
199469419bafSAndrew Jeffery        errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
199569419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
199669419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
199769419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
199869419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
199969419bafSAndrew Jeffery
200069419bafSAndrew Jeffery    try:
200169419bafSAndrew Jeffery        for i in range(3):
200269419bafSAndrew Jeffery            sensorReadings = sensor(host, args, session)
200369419bafSAndrew Jeffery            if 'OCC0' in sensorReadings:
200469419bafSAndrew Jeffery                sensorsCollected = True
200569419bafSAndrew Jeffery                break
200669419bafSAndrew Jeffery            else:
200769419bafSAndrew Jeffery                errorInfo += sensorReadings
200869419bafSAndrew Jeffery    except Exception as e:
200969419bafSAndrew Jeffery        errorInfo += "Sensor reading collection exception: {eInfo}\n".format(eInfo=e)
201069419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
201169419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
201269419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
201369419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
201469419bafSAndrew Jeffery    if sensorsCollected:
201569419bafSAndrew Jeffery        try:
201669419bafSAndrew Jeffery            with open(fileDir +os.sep+'sensorReadings.txt', 'w') as f:
201769419bafSAndrew Jeffery                f.write(sensorReadings)
201869419bafSAndrew Jeffery            print("Sensor readings collected and stored in " + fileDir + os.sep+ "sensorReadings.txt")
201969419bafSAndrew Jeffery            output['fileLoc'] = fileDir+os.sep+'sensorReadings.txt'
202069419bafSAndrew Jeffery        except Exception as e:
202169419bafSAndrew Jeffery            print("Failed to write sensor readings to file system.")
202269419bafSAndrew Jeffery            errorInfo += "Error writing sensor readings to the file. Exception: {eInfo}\n".format(eInfo=e)
202369419bafSAndrew Jeffery            exc_type, exc_obj, exc_tb = sys.exc_info()
202469419bafSAndrew Jeffery            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
202569419bafSAndrew Jeffery            errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
202669419bafSAndrew Jeffery            errorInfo += traceback.format_exc()
202769419bafSAndrew Jeffery
202869419bafSAndrew Jeffery    output['errors'] = errorInfo
202969419bafSAndrew Jeffery    return output
203069419bafSAndrew Jeffery
203169419bafSAndrew Jefferydef csdLEDs(host,args, session, fileDir):
203269419bafSAndrew Jeffery    """
203369419bafSAndrew Jeffery        Collects the BMC LED status, retrying if necessary
203469419bafSAndrew Jeffery
203569419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
203669419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
203769419bafSAndrew Jeffery         @param session: the active session to use
203869419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
203969419bafSAndrew Jeffery         @param fileDir: string representation of the path to use for putting files created
204069419bafSAndrew Jeffery    """
204169419bafSAndrew Jeffery    errorInfo = "===========LEDs =============\n"
204269419bafSAndrew Jeffery    ledsCollected = False
204369419bafSAndrew Jeffery    output={}
204469419bafSAndrew Jeffery    try:
204569419bafSAndrew Jeffery        d = vars(args)
204669419bafSAndrew Jeffery        d['json'] = True
204769419bafSAndrew Jeffery    except Exception as e:
204869419bafSAndrew Jeffery        errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
204969419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
205069419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
205169419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
205269419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
205369419bafSAndrew Jeffery    try:
205469419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/led/enumerate"
205569419bafSAndrew Jeffery        httpHeader = {'Content-Type':'application/json'}
205669419bafSAndrew Jeffery        for i in range(3):
205769419bafSAndrew Jeffery            try:
205869419bafSAndrew Jeffery                ledRes = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
205969419bafSAndrew Jeffery                if ledRes.status_code == 200:
206069419bafSAndrew Jeffery                    ledsCollected = True
206169419bafSAndrew Jeffery                    leds = ledRes.json()['data']
206269419bafSAndrew Jeffery                    break
206369419bafSAndrew Jeffery                else:
206469419bafSAndrew Jeffery                    errorInfo += ledRes.text
206569419bafSAndrew Jeffery            except(requests.exceptions.Timeout):
206669419bafSAndrew Jeffery                errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
206769419bafSAndrew Jeffery            except(requests.exceptions.ConnectionError) as err:
206869419bafSAndrew Jeffery                errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
206969419bafSAndrew Jeffery                exc_type, exc_obj, exc_tb = sys.exc_info()
207069419bafSAndrew Jeffery                fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
207169419bafSAndrew Jeffery                errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
207269419bafSAndrew Jeffery                errorInfo += traceback.format_exc()
207369419bafSAndrew Jeffery    except Exception as e:
207469419bafSAndrew Jeffery        errorInfo += "LED status collection exception: {eInfo}\n".format(eInfo=e)
207569419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
207669419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
207769419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
207869419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
207969419bafSAndrew Jeffery
208069419bafSAndrew Jeffery    if ledsCollected:
208169419bafSAndrew Jeffery        try:
208269419bafSAndrew Jeffery            with open(fileDir +os.sep+'ledStatus.txt', 'w') as f:
208369419bafSAndrew Jeffery                f.write(json.dumps(leds, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
208469419bafSAndrew Jeffery            print("LED status collected and stored in " + fileDir + os.sep+ "ledStatus.txt")
208569419bafSAndrew Jeffery            output['fileLoc'] = fileDir+os.sep+'ledStatus.txt'
208669419bafSAndrew Jeffery        except Exception as e:
208769419bafSAndrew Jeffery            print("Failed to write LED status to file system.")
208869419bafSAndrew Jeffery            errorInfo += "Error writing LED status to the file. Exception: {eInfo}\n".format(eInfo=e)
208969419bafSAndrew Jeffery            exc_type, exc_obj, exc_tb = sys.exc_info()
209069419bafSAndrew Jeffery            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
209169419bafSAndrew Jeffery            errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
209269419bafSAndrew Jeffery            errorInfo += traceback.format_exc()
209369419bafSAndrew Jeffery
209469419bafSAndrew Jeffery    output['errors'] = errorInfo
209569419bafSAndrew Jeffery    return output
209669419bafSAndrew Jeffery
209769419bafSAndrew Jefferydef csdSelShortList(host, args, session, fileDir):
209869419bafSAndrew Jeffery    """
209969419bafSAndrew Jeffery        Collects the BMC log entries, retrying if necessary
210069419bafSAndrew Jeffery
210169419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
210269419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
210369419bafSAndrew Jeffery         @param session: the active session to use
210469419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
210569419bafSAndrew Jeffery         @param fileDir: string representation of the path to use for putting files created
210669419bafSAndrew Jeffery    """
210769419bafSAndrew Jeffery    errorInfo = "===========SEL Short List =============\n"
210869419bafSAndrew Jeffery    selsCollected = False
210969419bafSAndrew Jeffery    output={}
211069419bafSAndrew Jeffery    try:
211169419bafSAndrew Jeffery        d = vars(args)
211269419bafSAndrew Jeffery        d['json'] = False
211369419bafSAndrew Jeffery    except Exception as e:
211469419bafSAndrew Jeffery        errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
211569419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
211669419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
211769419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
211869419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
211969419bafSAndrew Jeffery
212069419bafSAndrew Jeffery    try:
212169419bafSAndrew Jeffery        for i in range(3):
212269419bafSAndrew Jeffery            sels = selPrint(host,args,session)
212369419bafSAndrew Jeffery            if '----Active Alerts----' in sels or 'No log entries found' in sels or '----Historical Alerts----' in sels:
212469419bafSAndrew Jeffery                selsCollected = True
212569419bafSAndrew Jeffery                break
212669419bafSAndrew Jeffery            else:
212769419bafSAndrew Jeffery                errorInfo += sels + '\n'
212869419bafSAndrew Jeffery    except Exception as e:
212969419bafSAndrew Jeffery        errorInfo += "SEL short list collection exception: {eInfo}\n".format(eInfo=e)
213069419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
213169419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
213269419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
213369419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
213469419bafSAndrew Jeffery
213569419bafSAndrew Jeffery    if selsCollected:
213669419bafSAndrew Jeffery        try:
213769419bafSAndrew Jeffery            with open(fileDir +os.sep+'SELshortlist.txt', 'w') as f:
213869419bafSAndrew Jeffery                f.write(sels)
213969419bafSAndrew Jeffery            print("SEL short list collected and stored in " + fileDir + os.sep+ "SELshortlist.txt")
214069419bafSAndrew Jeffery            output['fileLoc'] = fileDir+os.sep+'SELshortlist.txt'
214169419bafSAndrew Jeffery        except Exception as e:
214269419bafSAndrew Jeffery            print("Failed to write SEL short list to file system.")
214369419bafSAndrew Jeffery            errorInfo += "Error writing SEL short list to the file. Exception: {eInfo}\n".format(eInfo=e)
214469419bafSAndrew Jeffery            exc_type, exc_obj, exc_tb = sys.exc_info()
214569419bafSAndrew Jeffery            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
214669419bafSAndrew Jeffery            errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
214769419bafSAndrew Jeffery            errorInfo += traceback.format_exc()
214869419bafSAndrew Jeffery
214969419bafSAndrew Jeffery    output['errors'] = errorInfo
215069419bafSAndrew Jeffery    return output
215169419bafSAndrew Jeffery
215269419bafSAndrew Jefferydef csdParsedSels(host, args, session, fileDir):
215369419bafSAndrew Jeffery    """
215469419bafSAndrew Jeffery        Collects the BMC log entries, retrying if necessary
215569419bafSAndrew Jeffery
215669419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
215769419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
215869419bafSAndrew Jeffery         @param session: the active session to use
215969419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
216069419bafSAndrew Jeffery         @param fileDir: string representation of the path to use for putting files created
216169419bafSAndrew Jeffery    """
216269419bafSAndrew Jeffery    errorInfo = "===========SEL Parsed List =============\n"
216369419bafSAndrew Jeffery    selsCollected = False
216469419bafSAndrew Jeffery    output={}
216569419bafSAndrew Jeffery    try:
216669419bafSAndrew Jeffery        d = vars(args)
216769419bafSAndrew Jeffery        d['json'] = True
216869419bafSAndrew Jeffery        d['fullEsel'] = True
216969419bafSAndrew Jeffery    except Exception as e:
217069419bafSAndrew Jeffery        errorInfo += "Failed to set the json flag to True \n Exception: {eInfo}\n".format(eInfo=e)
217169419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
217269419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
217369419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
217469419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
217569419bafSAndrew Jeffery
217669419bafSAndrew Jeffery    try:
217769419bafSAndrew Jeffery        for i in range(3):
217869419bafSAndrew Jeffery            parsedfullsels = json.loads(selPrint(host,args,session))
217969419bafSAndrew Jeffery            if 'numAlerts' in parsedfullsels:
218069419bafSAndrew Jeffery                selsCollected = True
218169419bafSAndrew Jeffery                break
218269419bafSAndrew Jeffery            else:
218369419bafSAndrew Jeffery                errorInfo += parsedfullsels + '\n'
218469419bafSAndrew Jeffery    except Exception as e:
218569419bafSAndrew Jeffery        errorInfo += "Parsed full SELs collection exception: {eInfo}\n".format(eInfo=e)
218669419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
218769419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
218869419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
218969419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
219069419bafSAndrew Jeffery
219169419bafSAndrew Jeffery    if selsCollected:
219269419bafSAndrew Jeffery        try:
219369419bafSAndrew Jeffery            sortedSELs = sortSELs(parsedfullsels)
219469419bafSAndrew Jeffery            with open(fileDir +os.sep+'parsedSELs.txt', 'w') as f:
219569419bafSAndrew Jeffery                for log in sortedSELs[0]:
219669419bafSAndrew Jeffery                    esel = ""
219769419bafSAndrew Jeffery                    parsedfullsels[sortedSELs[1][str(log)]]['timestamp'] = datetime.datetime.fromtimestamp(int(parsedfullsels[sortedSELs[1][str(log)]]['timestamp']/1000)).strftime("%Y-%m-%d %H:%M:%S")
219869419bafSAndrew Jeffery                    if ('raweSEL' in parsedfullsels[sortedSELs[1][str(log)]] and args.devdebug):
219969419bafSAndrew Jeffery                        esel = parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
220069419bafSAndrew Jeffery                        del parsedfullsels[sortedSELs[1][str(log)]]['raweSEL']
220169419bafSAndrew Jeffery                    f.write(json.dumps(parsedfullsels[sortedSELs[1][str(log)]],sort_keys=True, indent=4, separators=(',', ': ')))
220269419bafSAndrew Jeffery                    if(args.devdebug and esel != ""):
220369419bafSAndrew Jeffery                        f.write(parseESEL(args, esel))
220469419bafSAndrew Jeffery            print("Parsed SELs collected and stored in " + fileDir + os.sep+ "parsedSELs.txt")
220569419bafSAndrew Jeffery            output['fileLoc'] = fileDir+os.sep+'parsedSELs.txt'
220669419bafSAndrew Jeffery        except Exception as e:
220769419bafSAndrew Jeffery            print("Failed to write fully parsed SELs to file system.")
220869419bafSAndrew Jeffery            errorInfo += "Error writing fully parsed SELs to the file. Exception: {eInfo}\n".format(eInfo=e)
220969419bafSAndrew Jeffery            exc_type, exc_obj, exc_tb = sys.exc_info()
221069419bafSAndrew Jeffery            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
221169419bafSAndrew Jeffery            errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
221269419bafSAndrew Jeffery            errorInfo += traceback.format_exc()
221369419bafSAndrew Jeffery
221469419bafSAndrew Jeffery    output['errors'] = errorInfo
221569419bafSAndrew Jeffery    return output
221669419bafSAndrew Jeffery
221769419bafSAndrew Jefferydef csdFullEnumeration(host, args, session, fileDir):
221869419bafSAndrew Jeffery    """
221969419bafSAndrew Jeffery        Collects a full enumeration of /xyz/openbmc_project/, retrying if necessary
222069419bafSAndrew Jeffery
222169419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
222269419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
222369419bafSAndrew Jeffery         @param session: the active session to use
222469419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
222569419bafSAndrew Jeffery         @param fileDir: string representation of the path to use for putting files created
222669419bafSAndrew Jeffery    """
222769419bafSAndrew Jeffery    errorInfo = "===========BMC Full Enumeration =============\n"
222869419bafSAndrew Jeffery    bmcFullCollected = False
222969419bafSAndrew Jeffery    output={}
223069419bafSAndrew Jeffery    try:
223169419bafSAndrew Jeffery        d = vars(args)
223269419bafSAndrew Jeffery        d['json'] = True
223369419bafSAndrew Jeffery    except Exception as e:
223469419bafSAndrew Jeffery        errorInfo += "Failed to set the json flag to False \n Exception: {eInfo}\n".format(eInfo=e)
223569419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
223669419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
223769419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
223869419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
223969419bafSAndrew Jeffery    try:
224069419bafSAndrew Jeffery        print("Attempting to get a full BMC enumeration")
224169419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/enumerate"
224269419bafSAndrew Jeffery        httpHeader = {'Content-Type':'application/json'}
224369419bafSAndrew Jeffery        for i in range(3):
224469419bafSAndrew Jeffery            try:
224569419bafSAndrew Jeffery                bmcRes = session.get(url, headers=jsonHeader, verify=False, timeout=180)
224669419bafSAndrew Jeffery                if bmcRes.status_code == 200:
224769419bafSAndrew Jeffery                    bmcFullCollected = True
224869419bafSAndrew Jeffery                    fullEnumeration = bmcRes.json()
224969419bafSAndrew Jeffery                    break
225069419bafSAndrew Jeffery                else:
225169419bafSAndrew Jeffery                    errorInfo += bmcRes.text
225269419bafSAndrew Jeffery            except(requests.exceptions.Timeout):
225369419bafSAndrew Jeffery                errorInfo+=json.dumps( connectionErrHandler(args.json, "Timeout", None), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
225469419bafSAndrew Jeffery            except(requests.exceptions.ConnectionError) as err:
225569419bafSAndrew Jeffery                errorInfo += json.dumps(connectionErrHandler(args.json, "ConnectionError", err), sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n'
225669419bafSAndrew Jeffery                exc_type, exc_obj, exc_tb = sys.exc_info()
225769419bafSAndrew Jeffery                fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
225869419bafSAndrew Jeffery                errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
225969419bafSAndrew Jeffery                errorInfo += traceback.format_exc()
226069419bafSAndrew Jeffery    except Exception as e:
226169419bafSAndrew Jeffery        errorInfo += "RAW BMC data collection exception: {eInfo}\n".format(eInfo=e)
226269419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
226369419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
226469419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
226569419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
226669419bafSAndrew Jeffery
226769419bafSAndrew Jeffery    if bmcFullCollected:
226869419bafSAndrew Jeffery        try:
226969419bafSAndrew Jeffery            with open(fileDir +os.sep+'bmcFullRaw.txt', 'w') as f:
227069419bafSAndrew Jeffery                f.write(json.dumps(fullEnumeration, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False) + '\n')
227169419bafSAndrew Jeffery            print("RAW BMC data collected and saved into " + fileDir + os.sep+ "bmcFullRaw.txt")
227269419bafSAndrew Jeffery            output['fileLoc'] = fileDir+os.sep+'bmcFullRaw.txt'
227369419bafSAndrew Jeffery        except Exception as e:
227469419bafSAndrew Jeffery            print("Failed to write RAW BMC data  to file system.")
227569419bafSAndrew Jeffery            errorInfo += "Error writing RAW BMC data collection to the file. Exception: {eInfo}\n".format(eInfo=e)
227669419bafSAndrew Jeffery            exc_type, exc_obj, exc_tb = sys.exc_info()
227769419bafSAndrew Jeffery            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
227869419bafSAndrew Jeffery            errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
227969419bafSAndrew Jeffery            errorInfo += traceback.format_exc()
228069419bafSAndrew Jeffery
228169419bafSAndrew Jeffery    output['errors'] = errorInfo
228269419bafSAndrew Jeffery    return output
228369419bafSAndrew Jeffery
228469419bafSAndrew Jefferydef csdCollectAllDumps(host, args, session, fileDir):
228569419bafSAndrew Jeffery    """
228669419bafSAndrew Jeffery        Collects all of the bmc dump files and stores them in fileDir
228769419bafSAndrew Jeffery
228869419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
228969419bafSAndrew Jeffery        @param args: contains additional arguments used by the collectServiceData sub command
229069419bafSAndrew Jeffery        @param session: the active session to use
229169419bafSAndrew Jeffery        @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
229269419bafSAndrew Jeffery        @param fileDir: string representation of the path to use for putting files created
229369419bafSAndrew Jeffery    """
229469419bafSAndrew Jeffery
229569419bafSAndrew Jeffery    errorInfo = "===========BMC Dump Collection =============\n"
229669419bafSAndrew Jeffery    dumpListCollected = False
229769419bafSAndrew Jeffery    output={}
229869419bafSAndrew Jeffery    dumpList = {}
229969419bafSAndrew Jeffery    try:
230069419bafSAndrew Jeffery        d = vars(args)
230169419bafSAndrew Jeffery        d['json'] = True
230269419bafSAndrew Jeffery        d['dumpSaveLoc'] = fileDir
230369419bafSAndrew Jeffery    except Exception as e:
230469419bafSAndrew Jeffery        errorInfo += "Failed to set the json flag to True, or failed to set the dumpSave Location \n Exception: {eInfo}\n".format(eInfo=e)
230569419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
230669419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
230769419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
230869419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
230969419bafSAndrew Jeffery
231069419bafSAndrew Jeffery    print('Collecting bmc dump files')
231169419bafSAndrew Jeffery
231269419bafSAndrew Jeffery    try:
231369419bafSAndrew Jeffery        for i in range(3):
231469419bafSAndrew Jeffery            dumpResp = bmcDumpList(host, args, session)
231569419bafSAndrew Jeffery            if 'message' in dumpResp:
231669419bafSAndrew Jeffery                if 'ok' in dumpResp['message'].lower():
231769419bafSAndrew Jeffery                    dumpList = dumpResp['data']
231869419bafSAndrew Jeffery                    dumpListCollected = True
231969419bafSAndrew Jeffery                    break
232069419bafSAndrew Jeffery                else:
232169419bafSAndrew Jeffery                    errorInfo += "Status was not OK when retrieving the list of dumps available. \n Response: \n{resp}\n".format(resp=dumpResp)
232269419bafSAndrew Jeffery            else:
232369419bafSAndrew Jeffery                errorInfo += "Invalid response received from the BMC while retrieving the list of dumps available.\n {resp}\n".format(resp=dumpResp)
232469419bafSAndrew Jeffery    except Exception as e:
232569419bafSAndrew Jeffery        errorInfo += "BMC dump list exception: {eInfo}\n".format(eInfo=e)
232669419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
232769419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
232869419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
232969419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
233069419bafSAndrew Jeffery
233169419bafSAndrew Jeffery    if dumpListCollected:
233269419bafSAndrew Jeffery        output['fileList'] = []
233369419bafSAndrew Jeffery        for dump in dumpList:
233469419bafSAndrew Jeffery            try:
233569419bafSAndrew Jeffery                if '/xyz/openbmc_project/dump/internal/manager' not in dump:
233669419bafSAndrew Jeffery                    d['dumpNum'] = int(dump.strip().split('/')[-1])
233769419bafSAndrew Jeffery                    print('retrieving dump file ' + str(d['dumpNum']))
233869419bafSAndrew Jeffery                    filename = bmcDumpRetrieve(host, args, session).split('Saved as ')[-1]
233969419bafSAndrew Jeffery                    output['fileList'].append(filename)
234069419bafSAndrew Jeffery            except Exception as e:
234169419bafSAndrew Jeffery                print("Unable to collect dump: {dumpInfo}".format(dumpInfo=dump))
234269419bafSAndrew Jeffery                errorInfo += "Exception collecting a bmc dump {dumpInfo}\n {eInfo}\n".format(dumpInfo=dump, eInfo=e)
234369419bafSAndrew Jeffery                exc_type, exc_obj, exc_tb = sys.exc_info()
234469419bafSAndrew Jeffery                fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
234569419bafSAndrew Jeffery                errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
234669419bafSAndrew Jeffery                errorInfo += traceback.format_exc()
234769419bafSAndrew Jeffery    output['errors'] = errorInfo
234869419bafSAndrew Jeffery    return output
234969419bafSAndrew Jeffery
235069419bafSAndrew Jefferydef collectServiceData(host, args, session):
235169419bafSAndrew Jeffery    """
235269419bafSAndrew Jeffery         Collects all data needed for service from the BMC
235369419bafSAndrew Jeffery
235469419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
235569419bafSAndrew Jeffery         @param args: contains additional arguments used by the collectServiceData sub command
235669419bafSAndrew Jeffery         @param session: the active session to use
235769419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
235869419bafSAndrew Jeffery    """
235969419bafSAndrew Jeffery
236069419bafSAndrew Jeffery    global toolVersion
236169419bafSAndrew Jeffery    filelist = []
236269419bafSAndrew Jeffery    errorInfo = ""
236369419bafSAndrew Jeffery
236469419bafSAndrew Jeffery    #get current number of bmc dumps and create a new bmc dump
236569419bafSAndrew Jeffery    dumpInitdata = csdDumpInitiate(host, args, session)
236669419bafSAndrew Jeffery    if 'dumpFailure' in dumpInitdata:
236769419bafSAndrew Jeffery        return 'Collect service data is stopping due to not being able to create a new dump. No service data was collected.'
236869419bafSAndrew Jeffery    dumpcount = dumpInitdata['dumpcount']
236969419bafSAndrew Jeffery    errorInfo += dumpInitdata['errors']
237069419bafSAndrew Jeffery    #create the directory to put files
237169419bafSAndrew Jeffery    try:
237269419bafSAndrew Jeffery        args.silent = True
237369419bafSAndrew Jeffery        myDir = tempfile.gettempdir()+os.sep + host + "--" + datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%S")
237469419bafSAndrew Jeffery        os.makedirs(myDir)
237569419bafSAndrew Jeffery
237669419bafSAndrew Jeffery    except Exception as e:
237769419bafSAndrew Jeffery        print('Unable to create the temporary directory for data collection. Ensure sufficient privileges to create temporary directory. Aborting.')
237869419bafSAndrew Jeffery        exc_type, exc_obj, exc_tb = sys.exc_info()
237969419bafSAndrew Jeffery        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
238069419bafSAndrew Jeffery        errorInfo += "Exception: Error: {err}, Details: {etype}, {fname}, {lineno}\n".format(err=e, etype=exc_type, fname=fname, lineno=exc_tb.tb_lineno)
238169419bafSAndrew Jeffery        errorInfo += traceback.format_exc()
238269419bafSAndrew Jeffery        return("Python exception: {eInfo}".format(eInfo = e))
238369419bafSAndrew Jeffery
238469419bafSAndrew Jeffery    #Collect Inventory
238569419bafSAndrew Jeffery    inventoryData = csdInventory(host, args, session, myDir)
238669419bafSAndrew Jeffery    if 'fileLoc' in inventoryData:
238769419bafSAndrew Jeffery        filelist.append(inventoryData['fileLoc'])
238869419bafSAndrew Jeffery    errorInfo += inventoryData['errors']
238969419bafSAndrew Jeffery    #Read all the sensor and OCC status
239069419bafSAndrew Jeffery    sensorData = csdSensors(host,args,session,myDir)
239169419bafSAndrew Jeffery    if 'fileLoc' in sensorData:
239269419bafSAndrew Jeffery        filelist.append(sensorData['fileLoc'])
239369419bafSAndrew Jeffery    errorInfo += sensorData['errors']
239469419bafSAndrew Jeffery    #Collect all of the LEDs status
239569419bafSAndrew Jeffery    ledStatus = csdLEDs(host, args, session, myDir)
239669419bafSAndrew Jeffery    if 'fileLoc' in ledStatus:
239769419bafSAndrew Jeffery        filelist.append(ledStatus['fileLoc'])
239869419bafSAndrew Jeffery    errorInfo += ledStatus['errors']
239969419bafSAndrew Jeffery
240069419bafSAndrew Jeffery    #Collect the bmc logs
240169419bafSAndrew Jeffery    selShort = csdSelShortList(host, args, session, myDir)
240269419bafSAndrew Jeffery    if 'fileLoc' in selShort:
240369419bafSAndrew Jeffery        filelist.append(selShort['fileLoc'])
240469419bafSAndrew Jeffery    errorInfo += selShort['errors']
240569419bafSAndrew Jeffery
240669419bafSAndrew Jeffery    parsedSELs = csdParsedSels(host, args, session, myDir)
240769419bafSAndrew Jeffery    if 'fileLoc' in parsedSELs:
240869419bafSAndrew Jeffery        filelist.append(parsedSELs['fileLoc'])
240969419bafSAndrew Jeffery    errorInfo += parsedSELs['errors']
241069419bafSAndrew Jeffery
241169419bafSAndrew Jeffery    #collect RAW bmc enumeration
241269419bafSAndrew Jeffery    bmcRaw = csdFullEnumeration(host, args, session, myDir)
241369419bafSAndrew Jeffery    if 'fileLoc' in bmcRaw:
241469419bafSAndrew Jeffery        filelist.append(bmcRaw['fileLoc'])
241569419bafSAndrew Jeffery    errorInfo += bmcRaw['errors']
241669419bafSAndrew Jeffery
241769419bafSAndrew Jeffery    #wait for new dump to finish being created
241869419bafSAndrew Jeffery    waitingForNewDump = True
241969419bafSAndrew Jeffery    count = 0;
242069419bafSAndrew Jeffery    print("Waiting for new BMC dump to finish being created. Wait time could be up to 5 minutes")
242169419bafSAndrew Jeffery    while(waitingForNewDump):
242269419bafSAndrew Jeffery        dumpList = bmcDumpList(host, args, session)['data']
242369419bafSAndrew Jeffery        if len(dumpList) > dumpcount:
242469419bafSAndrew Jeffery            waitingForNewDump = False
242569419bafSAndrew Jeffery            break;
242669419bafSAndrew Jeffery        elif(count>150):
242769419bafSAndrew Jeffery            print("Timed out waiting for bmc to make a new dump file. Continuing without it.")
242869419bafSAndrew Jeffery            break;
242969419bafSAndrew Jeffery        else:
243069419bafSAndrew Jeffery            time.sleep(2)
243169419bafSAndrew Jeffery        count += 1
243269419bafSAndrew Jeffery
243369419bafSAndrew Jeffery    #collect all of the dump files
243469419bafSAndrew Jeffery    getBMCDumps = csdCollectAllDumps(host, args, session, myDir)
243569419bafSAndrew Jeffery    if 'fileList' in getBMCDumps:
243669419bafSAndrew Jeffery        filelist+= getBMCDumps['fileList']
243769419bafSAndrew Jeffery    errorInfo += getBMCDumps['errors']
243869419bafSAndrew Jeffery
243969419bafSAndrew Jeffery    #write the runtime errors to a file
244069419bafSAndrew Jeffery    try:
244169419bafSAndrew Jeffery        with open(myDir +os.sep+'openbmctoolRuntimeErrors.txt', 'w') as f:
244269419bafSAndrew Jeffery            f.write(errorInfo)
244369419bafSAndrew Jeffery        print("OpenBMC tool runtime errors collected and stored in " + myDir + os.sep+ "openbmctoolRuntimeErrors.txt")
244469419bafSAndrew Jeffery        filelist.append(myDir+os.sep+'openbmctoolRuntimeErrors.txt')
244569419bafSAndrew Jeffery    except Exception as e:
244669419bafSAndrew Jeffery        print("Failed to write OpenBMC tool runtime errors to file system.")
244769419bafSAndrew Jeffery
244869419bafSAndrew Jeffery    #create the zip file
244969419bafSAndrew Jeffery    try:
245069419bafSAndrew Jeffery        filename = myDir.split(tempfile.gettempdir()+os.sep)[-1] + "_" + toolVersion + '_openbmc.zip'
245169419bafSAndrew Jeffery        zf = zipfile.ZipFile(myDir+os.sep + filename, 'w')
245269419bafSAndrew Jeffery        for myfile in filelist:
245369419bafSAndrew Jeffery            zf.write(myfile, os.path.basename(myfile))
245469419bafSAndrew Jeffery        zf.close()
245569419bafSAndrew Jeffery        print("Zip file with all collected data created and stored in: {fileInfo}".format(fileInfo=myDir+os.sep+filename))
245669419bafSAndrew Jeffery    except Exception as e:
245769419bafSAndrew Jeffery        print("Failed to create zip file with collected information")
245869419bafSAndrew Jeffery    return "data collection finished"
245969419bafSAndrew Jeffery
246069419bafSAndrew Jeffery
246169419bafSAndrew Jefferydef healthCheck(host, args, session):
246269419bafSAndrew Jeffery    """
246369419bafSAndrew Jeffery         runs a health check on the platform
246469419bafSAndrew Jeffery
246569419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
246669419bafSAndrew Jeffery         @param args: contains additional arguments used by the bmc sub command
246769419bafSAndrew Jeffery         @param session: the active session to use
246869419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
246969419bafSAndrew Jeffery    """
247069419bafSAndrew Jeffery    #check fru status and get as json to easily work through
247169419bafSAndrew Jeffery    d = vars(args)
247269419bafSAndrew Jeffery    useJson = d['json']
247369419bafSAndrew Jeffery    d['json'] = True
247469419bafSAndrew Jeffery    d['verbose']= False
247569419bafSAndrew Jeffery
247669419bafSAndrew Jeffery    frus = json.loads(fruStatus(host, args, session))
247769419bafSAndrew Jeffery
247869419bafSAndrew Jeffery    hwStatus= "OK"
247969419bafSAndrew Jeffery    performanceStatus = "OK"
248069419bafSAndrew Jeffery    for key in frus:
248169419bafSAndrew Jeffery        if frus[key]["Functional"] == "No" and frus[key]["Present"] == "Yes":
248269419bafSAndrew Jeffery            hwStatus= "Degraded"
248369419bafSAndrew Jeffery            if("power_supply" in key or "powersupply" in key):
248469419bafSAndrew Jeffery                gpuCount =0
248569419bafSAndrew Jeffery                for comp in frus:
248669419bafSAndrew Jeffery                    if "gv100card" in comp:
248769419bafSAndrew Jeffery                        gpuCount +=1
248869419bafSAndrew Jeffery                if gpuCount > 4:
248969419bafSAndrew Jeffery                    hwStatus = "Critical"
249069419bafSAndrew Jeffery                    performanceStatus="Degraded"
249169419bafSAndrew Jeffery                    break;
249269419bafSAndrew Jeffery            elif("fan" in key):
249369419bafSAndrew Jeffery                hwStatus = "Degraded"
249469419bafSAndrew Jeffery            else:
249569419bafSAndrew Jeffery                performanceStatus = "Degraded"
249669419bafSAndrew Jeffery    if useJson:
249769419bafSAndrew Jeffery        output = {"Hardware Status": hwStatus, "Performance": performanceStatus}
249869419bafSAndrew Jeffery        output = json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False)
249969419bafSAndrew Jeffery    else:
250069419bafSAndrew Jeffery        output = ("Hardware Status: " + hwStatus +
250169419bafSAndrew Jeffery                  "\nPerformance: " +performanceStatus )
250269419bafSAndrew Jeffery
250369419bafSAndrew Jeffery
250469419bafSAndrew Jeffery    #SW407886: Clear the duplicate entries
250569419bafSAndrew Jeffery    #collect the dups
250669419bafSAndrew Jeffery    d['devdebug'] = False
250769419bafSAndrew Jeffery    sels = json.loads(selPrint(host, args, session))
250869419bafSAndrew Jeffery    logNums2Clr = []
250969419bafSAndrew Jeffery    oldestLogNum={"logNum": "bogus" ,"key" : ""}
251069419bafSAndrew Jeffery    count = 0
251169419bafSAndrew Jeffery    if sels['numAlerts'] > 0:
251269419bafSAndrew Jeffery        for key in sels:
251369419bafSAndrew Jeffery            if "numAlerts" in key:
251469419bafSAndrew Jeffery                continue
251569419bafSAndrew Jeffery            try:
251669419bafSAndrew Jeffery                if "slave@00:00/00:00:00:06/sbefifo1-dev0/occ1-dev0" in sels[key]['Message']:
251769419bafSAndrew Jeffery                    count += 1
251869419bafSAndrew Jeffery                    if count > 1:
251969419bafSAndrew Jeffery                        #preserve first occurrence
252069419bafSAndrew Jeffery                        if sels[key]['timestamp'] < sels[oldestLogNum['key']]['timestamp']:
252169419bafSAndrew Jeffery                            oldestLogNum['key']=key
252269419bafSAndrew Jeffery                            oldestLogNum['logNum'] = sels[key]['logNum']
252369419bafSAndrew Jeffery                    else:
252469419bafSAndrew Jeffery                        oldestLogNum['key']=key
252569419bafSAndrew Jeffery                        oldestLogNum['logNum'] = sels[key]['logNum']
252669419bafSAndrew Jeffery                    logNums2Clr.append(sels[key]['logNum'])
252769419bafSAndrew Jeffery            except KeyError:
252869419bafSAndrew Jeffery                continue
252969419bafSAndrew Jeffery        if(count >0):
253069419bafSAndrew Jeffery            logNums2Clr.remove(oldestLogNum['logNum'])
253169419bafSAndrew Jeffery        #delete the dups
253269419bafSAndrew Jeffery        if count >1:
253369419bafSAndrew Jeffery            data = "{\"data\": [] }"
253469419bafSAndrew Jeffery            for logNum in logNums2Clr:
253569419bafSAndrew Jeffery                    url = "https://"+ host+ "/xyz/openbmc_project/logging/entry/"+logNum+"/action/Delete"
253669419bafSAndrew Jeffery                    try:
253769419bafSAndrew Jeffery                        session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
253869419bafSAndrew Jeffery                    except(requests.exceptions.Timeout):
253969419bafSAndrew Jeffery                        deleteFailed = True
254069419bafSAndrew Jeffery                    except(requests.exceptions.ConnectionError) as err:
254169419bafSAndrew Jeffery                        deleteFailed = True
254269419bafSAndrew Jeffery    #End of defect resolve code
254369419bafSAndrew Jeffery    d['json'] = useJson
254469419bafSAndrew Jeffery    return output
254569419bafSAndrew Jeffery
254669419bafSAndrew Jeffery
254769419bafSAndrew Jeffery
254869419bafSAndrew Jefferydef bmc(host, args, session):
254969419bafSAndrew Jeffery    """
255069419bafSAndrew Jeffery         handles various bmc level commands, currently bmc rebooting
255169419bafSAndrew Jeffery
255269419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
255369419bafSAndrew Jeffery         @param args: contains additional arguments used by the bmc sub command
255469419bafSAndrew Jeffery         @param session: the active session to use
255569419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
255669419bafSAndrew Jeffery    """
255769419bafSAndrew Jeffery    if(args.type is not None):
255869419bafSAndrew Jeffery        return bmcReset(host, args, session)
255969419bafSAndrew Jeffery    if(args.info):
256069419bafSAndrew Jeffery        return "Not implemented at this time"
256169419bafSAndrew Jeffery
256269419bafSAndrew Jeffery
256369419bafSAndrew Jeffery
256469419bafSAndrew Jefferydef bmcReset(host, args, session):
256569419bafSAndrew Jeffery    """
256669419bafSAndrew Jeffery         controls resetting the bmc. warm reset reboots the bmc, cold reset removes the configuration and reboots.
256769419bafSAndrew Jeffery
256869419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
256969419bafSAndrew Jeffery         @param args: contains additional arguments used by the bmcReset sub command
257069419bafSAndrew Jeffery         @param session: the active session to use
257169419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
257269419bafSAndrew Jeffery    """
257369419bafSAndrew Jeffery    if checkFWactivation(host, args, session):
257469419bafSAndrew Jeffery        return ("BMC reset control disabled during firmware activation")
257569419bafSAndrew Jeffery    if(args.type == "warm"):
257669419bafSAndrew Jeffery        print("\nAttempting to reboot the BMC...:")
257769419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
257869419bafSAndrew Jeffery        data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
257969419bafSAndrew Jeffery        res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
258069419bafSAndrew Jeffery        return res.text
258169419bafSAndrew Jeffery    elif(args.type =="cold"):
258269419bafSAndrew Jeffery        print("\nAttempting to reboot the BMC...:")
258369419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition"
258469419bafSAndrew Jeffery        data = '{"data":"xyz.openbmc_project.State.BMC.Transition.Reboot"}'
258569419bafSAndrew Jeffery        res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
258669419bafSAndrew Jeffery        return res.text
258769419bafSAndrew Jeffery    else:
258869419bafSAndrew Jeffery        return "invalid command"
258969419bafSAndrew Jeffery
259069419bafSAndrew Jefferydef gardClear(host, args, session):
259169419bafSAndrew Jeffery    """
259269419bafSAndrew Jeffery         clears the gard records from the bmc
259369419bafSAndrew Jeffery
259469419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
259569419bafSAndrew Jeffery         @param args: contains additional arguments used by the gardClear sub command
259669419bafSAndrew Jeffery         @param session: the active session to use
259769419bafSAndrew Jeffery    """
259869419bafSAndrew Jeffery    url="https://"+host+"/org/open_power/control/gard/action/Reset"
259969419bafSAndrew Jeffery    data = '{"data":[]}'
260069419bafSAndrew Jeffery    try:
260169419bafSAndrew Jeffery
260269419bafSAndrew Jeffery        res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
260369419bafSAndrew Jeffery        if res.status_code == 404:
260469419bafSAndrew Jeffery            return "Command not supported by this firmware version"
260569419bafSAndrew Jeffery        else:
260669419bafSAndrew Jeffery            return res.text
260769419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
260869419bafSAndrew Jeffery        return connectionErrHandler(args.json, "Timeout", None)
260969419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
261069419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
261169419bafSAndrew Jeffery
261269419bafSAndrew Jefferydef activateFWImage(host, args, session):
261369419bafSAndrew Jeffery    """
261469419bafSAndrew Jeffery         activates a firmware image on the bmc
261569419bafSAndrew Jeffery
261669419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
261769419bafSAndrew Jeffery         @param args: contains additional arguments used by the fwflash sub command
261869419bafSAndrew Jeffery         @param session: the active session to use
261969419bafSAndrew Jeffery         @param fwID: the unique ID of the fw image to activate
262069419bafSAndrew Jeffery    """
262169419bafSAndrew Jeffery    fwID = args.imageID
262269419bafSAndrew Jeffery
262369419bafSAndrew Jeffery    #determine the existing versions
262469419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/software/enumerate"
262569419bafSAndrew Jeffery    try:
262669419bafSAndrew Jeffery        resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
262769419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
262869419bafSAndrew Jeffery        return connectionErrHandler(args.json, "Timeout", None)
262969419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
263069419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
263169419bafSAndrew Jeffery    existingSoftware = json.loads(resp.text)['data']
263269419bafSAndrew Jeffery    altVersionID = ''
263369419bafSAndrew Jeffery    versionType = ''
263469419bafSAndrew Jeffery    imageKey = '/xyz/openbmc_project/software/'+fwID
263569419bafSAndrew Jeffery    if imageKey in existingSoftware:
263669419bafSAndrew Jeffery        versionType = existingSoftware[imageKey]['Purpose']
263769419bafSAndrew Jeffery    for key in existingSoftware:
263869419bafSAndrew Jeffery        if imageKey == key:
263969419bafSAndrew Jeffery            continue
264069419bafSAndrew Jeffery        if 'Purpose' in existingSoftware[key]:
264169419bafSAndrew Jeffery            if versionType == existingSoftware[key]['Purpose']:
264269419bafSAndrew Jeffery                altVersionID = key.split('/')[-1]
264369419bafSAndrew Jeffery
264469419bafSAndrew Jeffery
264569419bafSAndrew Jeffery
264669419bafSAndrew Jeffery
264769419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/attr/Priority"
264869419bafSAndrew Jeffery    url1="https://"+host+"/xyz/openbmc_project/software/"+ altVersionID + "/attr/Priority"
264969419bafSAndrew Jeffery    data = "{\"data\": 0}"
265069419bafSAndrew Jeffery    data1 = "{\"data\": 1 }"
265169419bafSAndrew Jeffery    try:
265269419bafSAndrew Jeffery        resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
265369419bafSAndrew Jeffery        resp1 = session.put(url1, headers=jsonHeader, data=data1, verify=False, timeout=baseTimeout)
265469419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
265569419bafSAndrew Jeffery        return connectionErrHandler(args.json, "Timeout", None)
265669419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
265769419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
265869419bafSAndrew Jeffery    if(not args.json):
265969419bafSAndrew Jeffery        if resp.status_code == 200 and resp1.status_code == 200:
266069419bafSAndrew Jeffery            return 'Firmware flash and activation completed. Please reboot the bmc and then boot the host OS for the changes to take effect. '
266169419bafSAndrew Jeffery        else:
266269419bafSAndrew Jeffery            return "Firmware activation failed."
266369419bafSAndrew Jeffery    else:
266469419bafSAndrew Jeffery        return resp.text + resp1.text
266569419bafSAndrew Jeffery
266669419bafSAndrew Jefferydef activateStatus(host, args, session):
266769419bafSAndrew Jeffery    if checkFWactivation(host, args, session):
266869419bafSAndrew Jeffery        return("Firmware is currently being activated. Do not reboot the BMC or start the Host OS")
266969419bafSAndrew Jeffery    else:
267069419bafSAndrew Jeffery        return("No firmware activations are pending")
267169419bafSAndrew Jeffery
267269419bafSAndrew Jefferydef extractFWimage(path, imageType):
267369419bafSAndrew Jeffery    """
267469419bafSAndrew Jeffery         extracts the bmc image and returns information about the package
267569419bafSAndrew Jeffery
267669419bafSAndrew Jeffery         @param path: the path and file name of the firmware image
267769419bafSAndrew Jeffery         @param imageType: The type of image the user is trying to flash. Host or BMC
267869419bafSAndrew Jeffery         @return: the image id associated with the package. returns an empty string on error.
267969419bafSAndrew Jeffery    """
268069419bafSAndrew Jeffery    f = tempfile.TemporaryFile()
268169419bafSAndrew Jeffery    tmpDir = tempfile.gettempdir()
268269419bafSAndrew Jeffery    newImageID = ""
268369419bafSAndrew Jeffery    if os.path.exists(path):
268469419bafSAndrew Jeffery        try:
268569419bafSAndrew Jeffery            imageFile = tarfile.open(path,'r')
268669419bafSAndrew Jeffery            contents = imageFile.getmembers()
268769419bafSAndrew Jeffery            for tf in contents:
268869419bafSAndrew Jeffery                if 'MANIFEST' in tf.name:
268969419bafSAndrew Jeffery                    imageFile.extract(tf.name, path=tmpDir)
269069419bafSAndrew Jeffery                    with open(tempfile.gettempdir() +os.sep+ tf.name, 'r') as imageInfo:
269169419bafSAndrew Jeffery                        for line in imageInfo:
269269419bafSAndrew Jeffery                            if 'purpose' in line:
269369419bafSAndrew Jeffery                                purpose = line.split('=')[1]
269469419bafSAndrew Jeffery                                if imageType not in purpose.split('.')[-1]:
269569419bafSAndrew Jeffery                                    print('The specified image is not for ' + imageType)
269669419bafSAndrew Jeffery                                    print('Please try again with the image for ' + imageType)
269769419bafSAndrew Jeffery                                    return ""
269869419bafSAndrew Jeffery                            if 'version' == line.split('=')[0]:
269969419bafSAndrew Jeffery                                version = line.split('=')[1].strip().encode('utf-8')
270069419bafSAndrew Jeffery                                m = hashlib.sha512()
270169419bafSAndrew Jeffery                                m.update(version)
270269419bafSAndrew Jeffery                                newImageID = m.hexdigest()[:8]
270369419bafSAndrew Jeffery                                break
270469419bafSAndrew Jeffery                    try:
270569419bafSAndrew Jeffery                        os.remove(tempfile.gettempdir() +os.sep+ tf.name)
270669419bafSAndrew Jeffery                    except OSError:
270769419bafSAndrew Jeffery                        pass
270869419bafSAndrew Jeffery                    return newImageID
270969419bafSAndrew Jeffery        except tarfile.ExtractError as e:
271069419bafSAndrew Jeffery            print('Unable to extract information from the firmware file.')
271169419bafSAndrew Jeffery            print('Ensure you have write access to the directory: ' + tmpDir)
271269419bafSAndrew Jeffery            return newImageID
271369419bafSAndrew Jeffery        except tarfile.TarError as e:
271469419bafSAndrew Jeffery            print('This is not a valid firmware file.')
271569419bafSAndrew Jeffery            return newImageID
271669419bafSAndrew Jeffery        print("This is not a valid firmware file.")
271769419bafSAndrew Jeffery        return newImageID
271869419bafSAndrew Jeffery    else:
271969419bafSAndrew Jeffery        print('The filename and path provided are not valid.')
272069419bafSAndrew Jeffery        return newImageID
272169419bafSAndrew Jeffery
272269419bafSAndrew Jefferydef getAllFWImageIDs(fwInvDict):
272369419bafSAndrew Jeffery    """
272469419bafSAndrew Jeffery         gets a list of all the firmware image IDs
272569419bafSAndrew Jeffery
272669419bafSAndrew Jeffery         @param fwInvDict: the dictionary to search for FW image IDs
272769419bafSAndrew Jeffery         @return: list containing string representation of the found image ids
272869419bafSAndrew Jeffery    """
272969419bafSAndrew Jeffery    idList = []
273069419bafSAndrew Jeffery    for key in fwInvDict:
273169419bafSAndrew Jeffery        if 'Version' in fwInvDict[key]:
273269419bafSAndrew Jeffery            idList.append(key.split('/')[-1])
273369419bafSAndrew Jeffery    return idList
273469419bafSAndrew Jeffery
273569419bafSAndrew Jefferydef fwFlash(host, args, session):
273669419bafSAndrew Jeffery    """
273769419bafSAndrew Jeffery         updates the bmc firmware and pnor firmware
273869419bafSAndrew Jeffery
273969419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
274069419bafSAndrew Jeffery         @param args: contains additional arguments used by the fwflash sub command
274169419bafSAndrew Jeffery         @param session: the active session to use
274269419bafSAndrew Jeffery    """
274369419bafSAndrew Jeffery    d = vars(args)
274469419bafSAndrew Jeffery    if(args.type == 'bmc'):
274569419bafSAndrew Jeffery        purp = 'BMC'
274669419bafSAndrew Jeffery    else:
274769419bafSAndrew Jeffery        purp = 'Host'
274869419bafSAndrew Jeffery
274969419bafSAndrew Jeffery    #check power state of the machine. No concurrent FW updates allowed
275069419bafSAndrew Jeffery    d['powcmd'] = 'status'
275169419bafSAndrew Jeffery    powerstate = chassisPower(host, args, session)
275269419bafSAndrew Jeffery    if 'Chassis Power State: On' in powerstate:
275369419bafSAndrew Jeffery        return("Aborting firmware update. Host is powered on. Please turn off the host and try again.")
275469419bafSAndrew Jeffery
275569419bafSAndrew Jeffery    #determine the existing images on the bmc
275669419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/software/enumerate"
275769419bafSAndrew Jeffery    try:
275869419bafSAndrew Jeffery        resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
275969419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
276069419bafSAndrew Jeffery        return connectionErrHandler(args.json, "Timeout", None)
276169419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
276269419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
276369419bafSAndrew Jeffery    oldsoftware = json.loads(resp.text)['data']
276469419bafSAndrew Jeffery
276569419bafSAndrew Jeffery    #Extract the tar and get information from the manifest file
276669419bafSAndrew Jeffery    newversionID = extractFWimage(args.fileloc, purp)
276769419bafSAndrew Jeffery    if  newversionID == "":
276869419bafSAndrew Jeffery        return "Unable to verify FW image."
276969419bafSAndrew Jeffery
277069419bafSAndrew Jeffery
277169419bafSAndrew Jeffery    #check if the new image is already on the bmc
277269419bafSAndrew Jeffery    if newversionID not in getAllFWImageIDs(oldsoftware):
277369419bafSAndrew Jeffery
277469419bafSAndrew Jeffery        #upload the file
277569419bafSAndrew Jeffery        httpHeader = {'Content-Type':'application/octet-stream'}
277669419bafSAndrew Jeffery        httpHeader.update(xAuthHeader)
277769419bafSAndrew Jeffery        url="https://"+host+"/upload/image"
277869419bafSAndrew Jeffery        data=open(args.fileloc,'rb').read()
277969419bafSAndrew Jeffery        print("Uploading file to BMC")
278069419bafSAndrew Jeffery        try:
278169419bafSAndrew Jeffery            resp = session.post(url, headers=httpHeader, data=data, verify=False)
278269419bafSAndrew Jeffery        except(requests.exceptions.Timeout):
278369419bafSAndrew Jeffery            return connectionErrHandler(args.json, "Timeout", None)
278469419bafSAndrew Jeffery        except(requests.exceptions.ConnectionError) as err:
278569419bafSAndrew Jeffery            return connectionErrHandler(args.json, "ConnectionError", err)
278669419bafSAndrew Jeffery        if resp.status_code != 200:
278769419bafSAndrew Jeffery            return "Failed to upload the file to the bmc"
278869419bafSAndrew Jeffery        else:
278969419bafSAndrew Jeffery            print("Upload complete.")
279069419bafSAndrew Jeffery
279169419bafSAndrew Jeffery        #verify bmc processed the image
279269419bafSAndrew Jeffery        software ={}
279369419bafSAndrew Jeffery        for i in range(0, 5):
279469419bafSAndrew Jeffery            url="https://"+host+"/xyz/openbmc_project/software/enumerate"
279569419bafSAndrew Jeffery            try:
279669419bafSAndrew Jeffery                resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
279769419bafSAndrew Jeffery            except(requests.exceptions.Timeout):
279869419bafSAndrew Jeffery                return connectionErrHandler(args.json, "Timeout", None)
279969419bafSAndrew Jeffery            except(requests.exceptions.ConnectionError) as err:
280069419bafSAndrew Jeffery                return connectionErrHandler(args.json, "ConnectionError", err)
280169419bafSAndrew Jeffery            software = json.loads(resp.text)['data']
280269419bafSAndrew Jeffery            #check if bmc is done processing the new image
280369419bafSAndrew Jeffery            if (newversionID in getAllFWImageIDs(software)):
280469419bafSAndrew Jeffery                break
280569419bafSAndrew Jeffery            else:
280669419bafSAndrew Jeffery                time.sleep(15)
280769419bafSAndrew Jeffery
280869419bafSAndrew Jeffery        #activate the new image
280969419bafSAndrew Jeffery        print("Activating new image: "+newversionID)
281069419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID + "/attr/RequestedActivation"
281169419bafSAndrew Jeffery        data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
281269419bafSAndrew Jeffery        try:
281369419bafSAndrew Jeffery            resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
281469419bafSAndrew Jeffery        except(requests.exceptions.Timeout):
281569419bafSAndrew Jeffery            return connectionErrHandler(args.json, "Timeout", None)
281669419bafSAndrew Jeffery        except(requests.exceptions.ConnectionError) as err:
281769419bafSAndrew Jeffery            return connectionErrHandler(args.json, "ConnectionError", err)
281869419bafSAndrew Jeffery
281969419bafSAndrew Jeffery        #wait for the activation to complete, timeout after ~1 hour
282069419bafSAndrew Jeffery        i=0
282169419bafSAndrew Jeffery        while i < 360:
282269419bafSAndrew Jeffery            url="https://"+host+"/xyz/openbmc_project/software/"+ newversionID
282369419bafSAndrew Jeffery            data = '{"data":"xyz.openbmc_project.Software.Activation.RequestedActivations.Active"}'
282469419bafSAndrew Jeffery            try:
282569419bafSAndrew Jeffery                resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
282669419bafSAndrew Jeffery            except(requests.exceptions.Timeout):
282769419bafSAndrew Jeffery                return connectionErrHandler(args.json, "Timeout", None)
282869419bafSAndrew Jeffery            except(requests.exceptions.ConnectionError) as err:
282969419bafSAndrew Jeffery                return connectionErrHandler(args.json, "ConnectionError", err)
283069419bafSAndrew Jeffery            fwInfo = json.loads(resp.text)['data']
283169419bafSAndrew Jeffery            if 'Activating' not in fwInfo['Activation'] and 'Activating' not in fwInfo['RequestedActivation']:
283269419bafSAndrew Jeffery                print('')
283369419bafSAndrew Jeffery                break
283469419bafSAndrew Jeffery            else:
283569419bafSAndrew Jeffery                sys.stdout.write('.')
283669419bafSAndrew Jeffery                sys.stdout.flush()
283769419bafSAndrew Jeffery                time.sleep(10) #check every 10 seconds
283869419bafSAndrew Jeffery        return "Firmware flash and activation completed. Please reboot the bmc and then boot the host OS for the changes to take effect. "
283969419bafSAndrew Jeffery    else:
284069419bafSAndrew Jeffery        print("This image has been found on the bmc. Activating image: " + newversionID)
284169419bafSAndrew Jeffery
284269419bafSAndrew Jeffery        d['imageID'] = newversionID
284369419bafSAndrew Jeffery        return activateFWImage(host, args, session)
284469419bafSAndrew Jeffery
284569419bafSAndrew Jefferydef getFWInventoryAttributes(rawFWInvItem, ID):
284669419bafSAndrew Jeffery    """
284769419bafSAndrew Jeffery         gets and lists all of the firmware in the system.
284869419bafSAndrew Jeffery
284969419bafSAndrew Jeffery         @return: returns a dictionary containing the image attributes
285069419bafSAndrew Jeffery    """
285169419bafSAndrew Jeffery    reqActivation = rawFWInvItem["RequestedActivation"].split('.')[-1]
285269419bafSAndrew Jeffery    pendingActivation = ""
285369419bafSAndrew Jeffery    if reqActivation == "None":
285469419bafSAndrew Jeffery        pendingActivation = "No"
285569419bafSAndrew Jeffery    else:
285669419bafSAndrew Jeffery        pendingActivation = "Yes"
285769419bafSAndrew Jeffery    firmwareAttr = {ID: {
285869419bafSAndrew Jeffery        "Purpose": rawFWInvItem["Purpose"].split('.')[-1],
285969419bafSAndrew Jeffery        "Version": rawFWInvItem["Version"],
286069419bafSAndrew Jeffery        "RequestedActivation": pendingActivation,
286169419bafSAndrew Jeffery        "ID": ID}}
286269419bafSAndrew Jeffery
286369419bafSAndrew Jeffery    if "ExtendedVersion" in rawFWInvItem:
286469419bafSAndrew Jeffery        firmwareAttr[ID]['ExtendedVersion'] = rawFWInvItem['ExtendedVersion'].split(',')
286569419bafSAndrew Jeffery    else:
286669419bafSAndrew Jeffery        firmwareAttr[ID]['ExtendedVersion'] = ""
286769419bafSAndrew Jeffery    return firmwareAttr
286869419bafSAndrew Jeffery
286969419bafSAndrew Jefferydef parseFWdata(firmwareDict):
287069419bafSAndrew Jeffery    """
287169419bafSAndrew Jeffery         creates a dictionary with parsed firmware data
287269419bafSAndrew Jeffery
287369419bafSAndrew Jeffery         @return: returns a dictionary containing the image attributes
287469419bafSAndrew Jeffery    """
287569419bafSAndrew Jeffery    firmwareInfoDict = {"Functional": {}, "Activated":{}, "NeedsActivated":{}}
287669419bafSAndrew Jeffery    for key in firmwareDict['data']:
287769419bafSAndrew Jeffery        #check for valid endpoint
287869419bafSAndrew Jeffery        if "Purpose" in firmwareDict['data'][key]:
287969419bafSAndrew Jeffery            id = key.split('/')[-1]
288069419bafSAndrew Jeffery            if firmwareDict['data'][key]['Activation'].split('.')[-1] == "Active":
288169419bafSAndrew Jeffery                fwActivated = True
288269419bafSAndrew Jeffery            else:
288369419bafSAndrew Jeffery                fwActivated = False
288469419bafSAndrew Jeffery            if 'Priority' in firmwareDict['data'][key]:
288569419bafSAndrew Jeffery                if firmwareDict['data'][key]['Priority'] == 0:
288669419bafSAndrew Jeffery                    firmwareInfoDict['Functional'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
288769419bafSAndrew Jeffery                elif firmwareDict['data'][key]['Priority'] >= 0 and fwActivated:
288869419bafSAndrew Jeffery                    firmwareInfoDict['Activated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
288969419bafSAndrew Jeffery                else:
289069419bafSAndrew Jeffery                    firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
289169419bafSAndrew Jeffery            else:
289269419bafSAndrew Jeffery                firmwareInfoDict['NeedsActivated'].update(getFWInventoryAttributes(firmwareDict['data'][key], id))
289369419bafSAndrew Jeffery    emptySections = []
289469419bafSAndrew Jeffery    for key in firmwareInfoDict:
289569419bafSAndrew Jeffery        if len(firmwareInfoDict[key])<=0:
289669419bafSAndrew Jeffery            emptySections.append(key)
289769419bafSAndrew Jeffery    for key in emptySections:
289869419bafSAndrew Jeffery        del firmwareInfoDict[key]
289969419bafSAndrew Jeffery    return firmwareInfoDict
290069419bafSAndrew Jeffery
290169419bafSAndrew Jefferydef displayFWInvenory(firmwareInfoDict, args):
290269419bafSAndrew Jeffery    """
290369419bafSAndrew Jeffery         gets and lists all of the firmware in the system.
290469419bafSAndrew Jeffery
290569419bafSAndrew Jeffery         @return: returns a string containing all of the firmware information
290669419bafSAndrew Jeffery    """
290769419bafSAndrew Jeffery    output = ""
290869419bafSAndrew Jeffery    if not args.json:
290969419bafSAndrew Jeffery        for key in firmwareInfoDict:
291069419bafSAndrew Jeffery            for subkey in firmwareInfoDict[key]:
291169419bafSAndrew Jeffery                firmwareInfoDict[key][subkey]['ExtendedVersion'] = str(firmwareInfoDict[key][subkey]['ExtendedVersion'])
291269419bafSAndrew Jeffery        if not args.verbose:
291369419bafSAndrew Jeffery            output = "---Running Images---\n"
291469419bafSAndrew Jeffery            colNames = ["Purpose", "Version", "ID"]
291569419bafSAndrew Jeffery            keylist = ["Purpose", "Version", "ID"]
291669419bafSAndrew Jeffery            output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
291769419bafSAndrew Jeffery            if "Activated" in firmwareInfoDict:
291869419bafSAndrew Jeffery                output += "\n---Available Images---\n"
291969419bafSAndrew Jeffery                output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
292069419bafSAndrew Jeffery            if "NeedsActivated" in firmwareInfoDict:
292169419bafSAndrew Jeffery                output += "\n---Needs Activated Images---\n"
292269419bafSAndrew Jeffery                output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
292369419bafSAndrew Jeffery
292469419bafSAndrew Jeffery        else:
292569419bafSAndrew Jeffery            output = "---Running Images---\n"
292669419bafSAndrew Jeffery            colNames = ["Purpose", "Version", "ID", "Pending Activation", "Extended Version"]
292769419bafSAndrew Jeffery            keylist = ["Purpose", "Version", "ID", "RequestedActivation", "ExtendedVersion"]
292869419bafSAndrew Jeffery            output += tableDisplay(keylist, colNames, firmwareInfoDict["Functional"])
292969419bafSAndrew Jeffery            if "Activated" in firmwareInfoDict:
293069419bafSAndrew Jeffery                output += "\n---Available Images---\n"
293169419bafSAndrew Jeffery                output += tableDisplay(keylist, colNames, firmwareInfoDict["Activated"])
293269419bafSAndrew Jeffery            if "NeedsActivated" in firmwareInfoDict:
293369419bafSAndrew Jeffery                output += "\n---Needs Activated Images---\n"
293469419bafSAndrew Jeffery                output += tableDisplay(keylist, colNames, firmwareInfoDict["NeedsActivated"])
293569419bafSAndrew Jeffery        return output
293669419bafSAndrew Jeffery    else:
293769419bafSAndrew Jeffery        return str(json.dumps(firmwareInfoDict, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
293869419bafSAndrew Jeffery
293969419bafSAndrew Jefferydef firmwareList(host, args, session):
294069419bafSAndrew Jeffery    """
294169419bafSAndrew Jeffery         gets and lists all of the firmware in the system.
294269419bafSAndrew Jeffery
294369419bafSAndrew Jeffery         @return: returns a string containing all of the firmware information
294469419bafSAndrew Jeffery    """
294569419bafSAndrew Jeffery    url="https://{hostname}/xyz/openbmc_project/software/enumerate".format(hostname=host)
294669419bafSAndrew Jeffery    try:
294769419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
294869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
294969419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
295069419bafSAndrew Jeffery    firmwareDict = json.loads(res.text)
295169419bafSAndrew Jeffery
295269419bafSAndrew Jeffery    #sort the received information
295369419bafSAndrew Jeffery    firmwareInfoDict = parseFWdata(firmwareDict)
295469419bafSAndrew Jeffery
295569419bafSAndrew Jeffery    #display the information
295669419bafSAndrew Jeffery    return displayFWInvenory(firmwareInfoDict, args)
295769419bafSAndrew Jeffery
295869419bafSAndrew Jeffery
295969419bafSAndrew Jefferydef deleteFWVersion(host, args, session):
296069419bafSAndrew Jeffery    """
296169419bafSAndrew Jeffery         deletes a firmware version on the BMC
296269419bafSAndrew Jeffery
296369419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the BMC
296469419bafSAndrew Jeffery         @param args: contains additional arguments used by the fwflash sub command
296569419bafSAndrew Jeffery         @param session: the active session to use
296669419bafSAndrew Jeffery         @param fwID: the unique ID of the fw version to delete
296769419bafSAndrew Jeffery    """
296869419bafSAndrew Jeffery    fwID = args.versionID
296969419bafSAndrew Jeffery
297069419bafSAndrew Jeffery    print("Deleting version: "+fwID)
297169419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/software/"+ fwID + "/action/Delete"
297269419bafSAndrew Jeffery    data = "{\"data\": [] }"
297369419bafSAndrew Jeffery
297469419bafSAndrew Jeffery    try:
297569419bafSAndrew Jeffery        res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
297669419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
297769419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
297869419bafSAndrew Jeffery    if res.status_code == 200:
297969419bafSAndrew Jeffery        return ('The firmware version has been deleted')
298069419bafSAndrew Jeffery    else:
298169419bafSAndrew Jeffery        return ('Unable to delete the specified firmware version')
298269419bafSAndrew Jeffery
2983*0b5b2041SKlaus Heinrich Kiwidef deleteFWAll(host, args, session):
2984*0b5b2041SKlaus Heinrich Kiwi    """
2985*0b5b2041SKlaus Heinrich Kiwi         deletes ALL contents for firmware software catalog
2986*0b5b2041SKlaus Heinrich Kiwi
2987*0b5b2041SKlaus Heinrich Kiwi         @param host: string, the hostname or IP address of the BMC
2988*0b5b2041SKlaus Heinrich Kiwi         @param args: contains additional arguments used by the fwflash sub command
2989*0b5b2041SKlaus Heinrich Kiwi         @param session: the active session to use
2990*0b5b2041SKlaus Heinrich Kiwi    """
2991*0b5b2041SKlaus Heinrich Kiwi
2992*0b5b2041SKlaus Heinrich Kiwi    print("Deleting ALL firmware versions")
2993*0b5b2041SKlaus Heinrich Kiwi    url="https://"+host+"/xyz/openbmc_project/software/action/DeleteAll"
2994*0b5b2041SKlaus Heinrich Kiwi    data = "{\"data\": [] }"
2995*0b5b2041SKlaus Heinrich Kiwi
2996*0b5b2041SKlaus Heinrich Kiwi    try:
2997*0b5b2041SKlaus Heinrich Kiwi        res = session.post(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
2998*0b5b2041SKlaus Heinrich Kiwi    except(requests.exceptions.Timeout):
2999*0b5b2041SKlaus Heinrich Kiwi        return(connectionErrHandler(args.json, "Timeout", None))
3000*0b5b2041SKlaus Heinrich Kiwi    if res.status_code == 200:
3001*0b5b2041SKlaus Heinrich Kiwi        return ('All firmware versions were deleted')
3002*0b5b2041SKlaus Heinrich Kiwi    else:
3003*0b5b2041SKlaus Heinrich Kiwi        return ('Uspecified error while deleting All firmware versions')
3004*0b5b2041SKlaus Heinrich Kiwi
300569419bafSAndrew Jeffery
300669419bafSAndrew Jefferydef restLogging(host, args, session):
300769419bafSAndrew Jeffery    """
300869419bafSAndrew Jeffery         Called by the logging function. Turns REST API logging on/off.
300969419bafSAndrew Jeffery
301069419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
301169419bafSAndrew Jeffery         @param args: contains additional arguments used by the logging sub command
301269419bafSAndrew Jeffery         @param session: the active session to use
301369419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
301469419bafSAndrew Jeffery    """
301569419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/logging/rest_api_logs/attr/Enabled"
301669419bafSAndrew Jeffery
301769419bafSAndrew Jeffery    if(args.rest_logging == 'on'):
301869419bafSAndrew Jeffery        data = '{"data": 1}'
301969419bafSAndrew Jeffery    elif(args.rest_logging == 'off'):
302069419bafSAndrew Jeffery        data = '{"data": 0}'
302169419bafSAndrew Jeffery    else:
302269419bafSAndrew Jeffery        return "Invalid logging rest_api command"
302369419bafSAndrew Jeffery
302469419bafSAndrew Jeffery    try:
302569419bafSAndrew Jeffery        res = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
302669419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
302769419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
302869419bafSAndrew Jeffery    return res.text
302969419bafSAndrew Jeffery
303069419bafSAndrew Jeffery
303169419bafSAndrew Jefferydef remoteLogging(host, args, session):
303269419bafSAndrew Jeffery    """
303369419bafSAndrew Jeffery         Called by the logging function. View config information for/disable remote logging (rsyslog).
303469419bafSAndrew Jeffery
303569419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
303669419bafSAndrew Jeffery         @param args: contains additional arguments used by the logging sub command
303769419bafSAndrew Jeffery         @param session: the active session to use
303869419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
303969419bafSAndrew Jeffery    """
304069419bafSAndrew Jeffery
304169419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
304269419bafSAndrew Jeffery
304369419bafSAndrew Jeffery    try:
304469419bafSAndrew Jeffery        if(args.remote_logging == 'view'):
304569419bafSAndrew Jeffery            res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
304669419bafSAndrew Jeffery        elif(args.remote_logging == 'disable'):
304769419bafSAndrew Jeffery            res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": 0}, verify=False, timeout=baseTimeout)
304869419bafSAndrew Jeffery            res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": ""}, verify=False, timeout=baseTimeout)
304969419bafSAndrew Jeffery        else:
305069419bafSAndrew Jeffery            return "Invalid logging remote_logging command"
305169419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
305269419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
305369419bafSAndrew Jeffery    return res.text
305469419bafSAndrew Jeffery
305569419bafSAndrew Jeffery
305669419bafSAndrew Jefferydef remoteLoggingConfig(host, args, session):
305769419bafSAndrew Jeffery    """
305869419bafSAndrew Jeffery         Called by the logging function. Configures remote logging (rsyslog).
305969419bafSAndrew Jeffery
306069419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
306169419bafSAndrew Jeffery         @param args: contains additional arguments used by the logging sub command
306269419bafSAndrew Jeffery         @param session: the active session to use
306369419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption
306469419bafSAndrew Jeffery    """
306569419bafSAndrew Jeffery
306669419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/logging/config/remote"
306769419bafSAndrew Jeffery
306869419bafSAndrew Jeffery    try:
306969419bafSAndrew Jeffery        res = session.put(url + '/attr/Port', headers=jsonHeader, json = {"data": args.port}, verify=False, timeout=baseTimeout)
307069419bafSAndrew Jeffery        res = session.put(url + '/attr/Address', headers=jsonHeader, json = {"data": args.address}, verify=False, timeout=baseTimeout)
307169419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
307269419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
307369419bafSAndrew Jeffery    return res.text
307469419bafSAndrew Jeffery
307569419bafSAndrew Jefferydef redfishSupportPresent(host, session):
307669419bafSAndrew Jeffery    url = "https://" + host + "/redfish/v1"
307769419bafSAndrew Jeffery    try:
307869419bafSAndrew Jeffery        resp = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
307969419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
308069419bafSAndrew Jeffery        return False
308169419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
308269419bafSAndrew Jeffery        return False
308369419bafSAndrew Jeffery    if resp.status_code != 200:
308469419bafSAndrew Jeffery        return False
308569419bafSAndrew Jeffery    else:
308669419bafSAndrew Jeffery       return True
308769419bafSAndrew Jeffery
308869419bafSAndrew Jefferydef certificateUpdate(host, args, session):
308969419bafSAndrew Jeffery    """
309069419bafSAndrew Jeffery         Called by certificate management function. update server/client/authority certificates
309169419bafSAndrew Jeffery         Example:
309269419bafSAndrew Jeffery         certificate update server https -f cert.pem
309369419bafSAndrew Jeffery         certificate update authority ldap -f Root-CA.pem
309469419bafSAndrew Jeffery         certificate update client ldap -f cert.pem
309569419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
309669419bafSAndrew Jeffery         @param args: contains additional arguments used by the certificate update sub command
309769419bafSAndrew Jeffery         @param session: the active session to use
309869419bafSAndrew Jeffery    """
309969419bafSAndrew Jeffery    httpHeader = {'Content-Type': 'application/octet-stream'}
310069419bafSAndrew Jeffery    httpHeader.update(xAuthHeader)
310169419bafSAndrew Jeffery    data = open(args.fileloc, 'r').read()
310269419bafSAndrew Jeffery    try:
310369419bafSAndrew Jeffery        if redfishSupportPresent(host, session):
310469419bafSAndrew Jeffery            if(args.type.lower() == 'server' and args.service.lower() != "https"):
310569419bafSAndrew Jeffery                return "Invalid service type"
310669419bafSAndrew Jeffery            if(args.type.lower() == 'client' and args.service.lower() != "ldap"):
310769419bafSAndrew Jeffery                return "Invalid service type"
310869419bafSAndrew Jeffery            if(args.type.lower() == 'authority' and args.service.lower() != "ldap"):
310969419bafSAndrew Jeffery                return "Invalid service type"
311069419bafSAndrew Jeffery            url = "";
311169419bafSAndrew Jeffery            if(args.type.lower() == 'server'):
311269419bafSAndrew Jeffery                url = "https://" + host + \
311369419bafSAndrew Jeffery                    "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"
311469419bafSAndrew Jeffery            elif(args.type.lower() == 'client'):
311569419bafSAndrew Jeffery                url = "https://" + host + \
311669419bafSAndrew Jeffery                    "/redfish/v1/AccountService/LDAP/Certificates"
311769419bafSAndrew Jeffery            elif(args.type.lower() == 'authority'):
311869419bafSAndrew Jeffery                url = "https://" + host + \
311969419bafSAndrew Jeffery                "/redfish/v1/Managers/bmc/Truststore/Certificates"
312069419bafSAndrew Jeffery            else:
312169419bafSAndrew Jeffery                return "Unsupported certificate type"
312269419bafSAndrew Jeffery            resp = session.post(url, headers=httpHeader, data=data,
312369419bafSAndrew Jeffery                        verify=False)
312469419bafSAndrew Jeffery        else:
312569419bafSAndrew Jeffery            url = "https://" + host + "/xyz/openbmc_project/certs/" + \
312669419bafSAndrew Jeffery                args.type.lower() + "/" + args.service.lower()
312769419bafSAndrew Jeffery            resp = session.put(url, headers=httpHeader, data=data, verify=False)
312869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
312969419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
313069419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
313169419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
313269419bafSAndrew Jeffery    if resp.status_code != 200:
313369419bafSAndrew Jeffery        print(resp.text)
313469419bafSAndrew Jeffery        return "Failed to update the certificate"
313569419bafSAndrew Jeffery    else:
313669419bafSAndrew Jeffery        print("Update complete.")
313769419bafSAndrew Jeffery
313869419bafSAndrew Jefferydef certificateDelete(host, args, session):
313969419bafSAndrew Jeffery    """
314069419bafSAndrew Jeffery         Called by certificate management function to delete certificate
314169419bafSAndrew Jeffery         Example:
314269419bafSAndrew Jeffery         certificate delete server https
314369419bafSAndrew Jeffery         certificate delete authority ldap
314469419bafSAndrew Jeffery         certificate delete client ldap
314569419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
314669419bafSAndrew Jeffery         @param args: contains additional arguments used by the certificate delete sub command
314769419bafSAndrew Jeffery         @param session: the active session to use
314869419bafSAndrew Jeffery    """
314969419bafSAndrew Jeffery    if redfishSupportPresent(host, session):
315069419bafSAndrew Jeffery        return "Not supported, please use certificate replace instead";
315169419bafSAndrew Jeffery    httpHeader = {'Content-Type': 'multipart/form-data'}
315269419bafSAndrew Jeffery    httpHeader.update(xAuthHeader)
315369419bafSAndrew Jeffery    url = "https://" + host + "/xyz/openbmc_project/certs/" + args.type.lower() + "/" + args.service.lower()
315469419bafSAndrew Jeffery    print("Deleting certificate url=" + url)
315569419bafSAndrew Jeffery    try:
315669419bafSAndrew Jeffery        resp = session.delete(url, headers=httpHeader)
315769419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
315869419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
315969419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
316069419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
316169419bafSAndrew Jeffery    if resp.status_code != 200:
316269419bafSAndrew Jeffery        print(resp.text)
316369419bafSAndrew Jeffery        return "Failed to delete the certificate"
316469419bafSAndrew Jeffery    else:
316569419bafSAndrew Jeffery        print("Delete complete.")
316669419bafSAndrew Jeffery
316769419bafSAndrew Jefferydef certificateReplace(host, args, session):
316869419bafSAndrew Jeffery    """
316969419bafSAndrew Jeffery         Called by certificate management function. replace server/client/
317069419bafSAndrew Jeffery         authority certificates
317169419bafSAndrew Jeffery         Example:
317269419bafSAndrew Jeffery         certificate replace server https -f cert.pem
317369419bafSAndrew Jeffery         certificate replace authority ldap -f Root-CA.pem
317469419bafSAndrew Jeffery         certificate replace client ldap -f cert.pem
317569419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
317669419bafSAndrew Jeffery         @param args: contains additional arguments used by the certificate
317769419bafSAndrew Jeffery                      replace sub command
317869419bafSAndrew Jeffery         @param session: the active session to use
317969419bafSAndrew Jeffery    """
318069419bafSAndrew Jeffery    cert = open(args.fileloc, 'r').read()
318169419bafSAndrew Jeffery    try:
318269419bafSAndrew Jeffery        if redfishSupportPresent(host, session):
318369419bafSAndrew Jeffery            httpHeader = {'Content-Type': 'application/json'}
318469419bafSAndrew Jeffery            httpHeader.update(xAuthHeader)
318569419bafSAndrew Jeffery            url = "";
318669419bafSAndrew Jeffery            if(args.type.lower() == 'server' and args.service.lower() != "https"):
318769419bafSAndrew Jeffery                return "Invalid service type"
318869419bafSAndrew Jeffery            if(args.type.lower() == 'client' and args.service.lower() != "ldap"):
318969419bafSAndrew Jeffery                return "Invalid service type"
319069419bafSAndrew Jeffery            if(args.type.lower() == 'authority' and args.service.lower() != "ldap"):
319169419bafSAndrew Jeffery                return "Invalid service type"
319269419bafSAndrew Jeffery            if(args.type.lower() == 'server'):
319369419bafSAndrew Jeffery                url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
319469419bafSAndrew Jeffery            elif(args.type.lower() == 'client'):
319569419bafSAndrew Jeffery                url = "/redfish/v1/AccountService/LDAP/Certificates/1"
319669419bafSAndrew Jeffery            elif(args.type.lower() == 'authority'):
319769419bafSAndrew Jeffery                url = "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
319869419bafSAndrew Jeffery            replaceUrl = "https://" + host + \
319969419bafSAndrew Jeffery                "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"
320069419bafSAndrew Jeffery            data ={"CertificateUri":{"@odata.id":url}, "CertificateType":"PEM",
320169419bafSAndrew Jeffery                    "CertificateString":cert}
320269419bafSAndrew Jeffery            resp = session.post(replaceUrl, headers=httpHeader, json=data, verify=False)
320369419bafSAndrew Jeffery        else:
320469419bafSAndrew Jeffery            httpHeader = {'Content-Type': 'application/octet-stream'}
320569419bafSAndrew Jeffery            httpHeader.update(xAuthHeader)
320669419bafSAndrew Jeffery            url = "https://" + host + "/xyz/openbmc_project/certs/" + \
320769419bafSAndrew Jeffery                args.type.lower() + "/" + args.service.lower()
320869419bafSAndrew Jeffery            resp = session.delete(url, headers=httpHeader)
320969419bafSAndrew Jeffery            resp = session.put(url, headers=httpHeader, data=cert, verify=False)
321069419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
321169419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
321269419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
321369419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
321469419bafSAndrew Jeffery    if resp.status_code != 200:
321569419bafSAndrew Jeffery        print(resp.text)
321669419bafSAndrew Jeffery        return "Failed to replace the certificate"
321769419bafSAndrew Jeffery    else:
321869419bafSAndrew Jeffery        print("Replace complete.")
321969419bafSAndrew Jeffery    return resp.text
322069419bafSAndrew Jeffery
322169419bafSAndrew Jefferydef certificateDisplay(host, args, session):
322269419bafSAndrew Jeffery    """
322369419bafSAndrew Jeffery         Called by certificate management function. display server/client/
322469419bafSAndrew Jeffery         authority certificates
322569419bafSAndrew Jeffery         Example:
322669419bafSAndrew Jeffery         certificate display server
322769419bafSAndrew Jeffery         certificate display authority
322869419bafSAndrew Jeffery         certificate display client
322969419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
323069419bafSAndrew Jeffery         @param args: contains additional arguments used by the certificate
323169419bafSAndrew Jeffery                      display sub command
323269419bafSAndrew Jeffery         @param session: the active session to use
323369419bafSAndrew Jeffery    """
323469419bafSAndrew Jeffery    if not redfishSupportPresent(host, session):
323569419bafSAndrew Jeffery        return "Not supported";
323669419bafSAndrew Jeffery
323769419bafSAndrew Jeffery    httpHeader = {'Content-Type': 'application/octet-stream'}
323869419bafSAndrew Jeffery    httpHeader.update(xAuthHeader)
323969419bafSAndrew Jeffery    if(args.type.lower() == 'server'):
324069419bafSAndrew Jeffery        url = "https://" + host + \
324169419bafSAndrew Jeffery            "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
324269419bafSAndrew Jeffery    elif(args.type.lower() == 'client'):
324369419bafSAndrew Jeffery        url = "https://" + host + \
324469419bafSAndrew Jeffery            "/redfish/v1/AccountService/LDAP/Certificates/1"
324569419bafSAndrew Jeffery    elif(args.type.lower() == 'authority'):
324669419bafSAndrew Jeffery        url = "https://" + host + \
324769419bafSAndrew Jeffery            "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
324869419bafSAndrew Jeffery    try:
324969419bafSAndrew Jeffery        resp = session.get(url, headers=httpHeader, verify=False)
325069419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
325169419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
325269419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
325369419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
325469419bafSAndrew Jeffery    if resp.status_code != 200:
325569419bafSAndrew Jeffery        print(resp.text)
325669419bafSAndrew Jeffery        return "Failed to display the certificate"
325769419bafSAndrew Jeffery    else:
325869419bafSAndrew Jeffery        print("Display complete.")
325969419bafSAndrew Jeffery    return resp.text
326069419bafSAndrew Jeffery
326169419bafSAndrew Jefferydef certificateList(host, args, session):
326269419bafSAndrew Jeffery    """
326369419bafSAndrew Jeffery         Called by certificate management function.
326469419bafSAndrew Jeffery         Example:
326569419bafSAndrew Jeffery         certificate list
326669419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
326769419bafSAndrew Jeffery         @param args: contains additional arguments used by the certificate
326869419bafSAndrew Jeffery                      list sub command
326969419bafSAndrew Jeffery         @param session: the active session to use
327069419bafSAndrew Jeffery    """
327169419bafSAndrew Jeffery    if not redfishSupportPresent(host, session):
327269419bafSAndrew Jeffery        return "Not supported";
327369419bafSAndrew Jeffery
327469419bafSAndrew Jeffery    httpHeader = {'Content-Type': 'application/octet-stream'}
327569419bafSAndrew Jeffery    httpHeader.update(xAuthHeader)
327669419bafSAndrew Jeffery    url = "https://" + host + \
327769419bafSAndrew Jeffery        "/redfish/v1/CertificateService/CertificateLocations/"
327869419bafSAndrew Jeffery    try:
327969419bafSAndrew Jeffery        resp = session.get(url, headers=httpHeader, verify=False)
328069419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
328169419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
328269419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
328369419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
328469419bafSAndrew Jeffery    if resp.status_code != 200:
328569419bafSAndrew Jeffery        print(resp.text)
328669419bafSAndrew Jeffery        return "Failed to list certificates"
328769419bafSAndrew Jeffery    else:
328869419bafSAndrew Jeffery        print("List certificates complete.")
328969419bafSAndrew Jeffery    return resp.text
329069419bafSAndrew Jeffery
329169419bafSAndrew Jefferydef certificateGenerateCSR(host, args, session):
329269419bafSAndrew Jeffery    """
329369419bafSAndrew Jeffery        Called by certificate management function. Generate CSR for server/
329469419bafSAndrew Jeffery        client certificates
329569419bafSAndrew Jeffery        Example:
329669419bafSAndrew Jeffery        certificate generatecsr server NJ w3.ibm.com US IBM IBM-UNIT NY EC prime256v1 cp abc.com an.com,bm.com gn sn un in
329769419bafSAndrew Jeffery        certificate generatecsr client NJ w3.ibm.com US IBM IBM-UNIT NY EC prime256v1 cp abc.com an.com,bm.com gn sn un in
329869419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
329969419bafSAndrew Jeffery        @param args: contains additional arguments used by the certificate replace sub command
330069419bafSAndrew Jeffery        @param session: the active session to use
330169419bafSAndrew Jeffery    """
330269419bafSAndrew Jeffery    if not redfishSupportPresent(host, session):
330369419bafSAndrew Jeffery        return "Not supported";
330469419bafSAndrew Jeffery
330569419bafSAndrew Jeffery    httpHeader = {'Content-Type': 'application/octet-stream'}
330669419bafSAndrew Jeffery    httpHeader.update(xAuthHeader)
330769419bafSAndrew Jeffery    url = "";
330869419bafSAndrew Jeffery    if(args.type.lower() == 'server'):
330969419bafSAndrew Jeffery        url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"
331069419bafSAndrew Jeffery        usage_list = ["ServerAuthentication"]
331169419bafSAndrew Jeffery    elif(args.type.lower() == 'client'):
331269419bafSAndrew Jeffery        url = "/redfish/v1/AccountService/LDAP/Certificates/"
331369419bafSAndrew Jeffery        usage_list = ["ClientAuthentication"]
331469419bafSAndrew Jeffery    elif(args.type.lower() == 'authority'):
331569419bafSAndrew Jeffery        url = "/redfish/v1/Managers/bmc/Truststore/Certificates/"
331669419bafSAndrew Jeffery    print("Generating CSR url=" + url)
331769419bafSAndrew Jeffery    generateCSRUrl = "https://" + host + \
331869419bafSAndrew Jeffery        "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"
331969419bafSAndrew Jeffery    try:
332069419bafSAndrew Jeffery        alt_name_list = args.alternativeNames.split(",")
332169419bafSAndrew Jeffery        data ={"CertificateCollection":{"@odata.id":url},
332269419bafSAndrew Jeffery            "CommonName":args.commonName, "City":args.city,
332369419bafSAndrew Jeffery            "Country":args.country, "Organization":args.organization,
332469419bafSAndrew Jeffery            "OrganizationalUnit":args.organizationUnit, "State":args.state,
332569419bafSAndrew Jeffery            "KeyPairAlgorithm":args.keyPairAlgorithm, "KeyCurveId":args.keyCurveId,
332669419bafSAndrew Jeffery            "AlternativeNames":alt_name_list, "ContactPerson":args.contactPerson,
332769419bafSAndrew Jeffery            "Email":args.email, "GivenName":args.givenname, "Initials":args.initials,
332869419bafSAndrew Jeffery            "KeyUsage":usage_list, "Surname":args.surname,
332969419bafSAndrew Jeffery            "UnstructuredName":args.unstructuredname}
333069419bafSAndrew Jeffery        resp = session.post(generateCSRUrl, headers=httpHeader,
333169419bafSAndrew Jeffery            json=data, verify=False)
333269419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
333369419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
333469419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
333569419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
333669419bafSAndrew Jeffery    if resp.status_code != 200:
333769419bafSAndrew Jeffery        print(resp.text)
333869419bafSAndrew Jeffery        return "Failed to generate CSR"
333969419bafSAndrew Jeffery    else:
334069419bafSAndrew Jeffery        print("GenerateCSR complete.")
334169419bafSAndrew Jeffery    return resp.text
334269419bafSAndrew Jeffery
334369419bafSAndrew Jefferydef enableLDAPConfig(host, args, session):
334469419bafSAndrew Jeffery    """
334569419bafSAndrew Jeffery         Called by the ldap function. Configures LDAP.
334669419bafSAndrew Jeffery
334769419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
334869419bafSAndrew Jeffery         @param args: contains additional arguments used by the ldap subcommand
334969419bafSAndrew Jeffery         @param session: the active session to use
335069419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will
335169419bafSAndrew Jeffery            be provided in json format for programmatic consumption
335269419bafSAndrew Jeffery    """
335369419bafSAndrew Jeffery
335469419bafSAndrew Jeffery    if(isRedfishSupport):
335569419bafSAndrew Jeffery        return enableLDAP(host, args, session)
335669419bafSAndrew Jeffery    else:
335769419bafSAndrew Jeffery        return enableLegacyLDAP(host, args, session)
335869419bafSAndrew Jeffery
335969419bafSAndrew Jefferydef enableLegacyLDAP(host, args, session):
336069419bafSAndrew Jeffery    """
336169419bafSAndrew Jeffery         Called by the ldap function. Configures LDAP on Lagecy systems.
336269419bafSAndrew Jeffery
336369419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
336469419bafSAndrew Jeffery         @param args: contains additional arguments used by the ldap subcommand
336569419bafSAndrew Jeffery         @param session: the active session to use
336669419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will
336769419bafSAndrew Jeffery            be provided in json format for programmatic consumption
336869419bafSAndrew Jeffery    """
336969419bafSAndrew Jeffery
337069419bafSAndrew Jeffery    url='https://'+host+'/xyz/openbmc_project/user/ldap/action/CreateConfig'
337169419bafSAndrew Jeffery    scope = {
337269419bafSAndrew Jeffery             'sub' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.sub',
337369419bafSAndrew Jeffery             'one' : 'xyz.openbmc_project.User.Ldap.Create.SearchScope.one',
337469419bafSAndrew Jeffery             'base': 'xyz.openbmc_project.User.Ldap.Create.SearchScope.base'
337569419bafSAndrew Jeffery            }
337669419bafSAndrew Jeffery
337769419bafSAndrew Jeffery    serverType = {
337869419bafSAndrew Jeffery             'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Create.Type.ActiveDirectory',
337969419bafSAndrew Jeffery             'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Create.Type.OpenLdap'
338069419bafSAndrew Jeffery            }
338169419bafSAndrew Jeffery
338269419bafSAndrew Jeffery    data = {"data": [args.uri, args.bindDN, args.baseDN, args.bindPassword, scope[args.scope], serverType[args.serverType]]}
338369419bafSAndrew Jeffery
338469419bafSAndrew Jeffery    try:
338569419bafSAndrew Jeffery        res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
338669419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
338769419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
338869419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
338969419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
339069419bafSAndrew Jeffery
339169419bafSAndrew Jeffery    return res.text
339269419bafSAndrew Jeffery
339369419bafSAndrew Jefferydef enableLDAP(host, args, session):
339469419bafSAndrew Jeffery    """
339569419bafSAndrew Jeffery         Called by the ldap function. Configures LDAP for systems with latest user-manager design changes
339669419bafSAndrew Jeffery
339769419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
339869419bafSAndrew Jeffery         @param args: contains additional arguments used by the ldap subcommand
339969419bafSAndrew Jeffery         @param session: the active session to use
340069419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output will
340169419bafSAndrew Jeffery            be provided in json format for programmatic consumption
340269419bafSAndrew Jeffery    """
340369419bafSAndrew Jeffery
340469419bafSAndrew Jeffery    scope = {
340569419bafSAndrew Jeffery             'sub' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.sub',
340669419bafSAndrew Jeffery             'one' : 'xyz.openbmc_project.User.Ldap.Config.SearchScope.one',
340769419bafSAndrew Jeffery             'base': 'xyz.openbmc_project.User.Ldap.Config.SearchScope.base'
340869419bafSAndrew Jeffery            }
340969419bafSAndrew Jeffery
341069419bafSAndrew Jeffery    serverType = {
341169419bafSAndrew Jeffery            'ActiveDirectory' : 'xyz.openbmc_project.User.Ldap.Config.Type.ActiveDirectory',
341269419bafSAndrew Jeffery            'OpenLDAP' : 'xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap'
341369419bafSAndrew Jeffery            }
341469419bafSAndrew Jeffery
341569419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
341669419bafSAndrew Jeffery
341769419bafSAndrew Jeffery    serverTypeEnabled = getLDAPTypeEnabled(host,session)
341869419bafSAndrew Jeffery    serverTypeToBeEnabled = args.serverType
341969419bafSAndrew Jeffery
342069419bafSAndrew Jeffery    #If the given LDAP type is already enabled, then return
342169419bafSAndrew Jeffery    if (serverTypeToBeEnabled == serverTypeEnabled):
342269419bafSAndrew Jeffery      return("Server type " + serverTypeToBeEnabled + " is already enabled...")
342369419bafSAndrew Jeffery
342469419bafSAndrew Jeffery    try:
342569419bafSAndrew Jeffery
342669419bafSAndrew Jeffery        #  Copy the role map from the currently enabled LDAP server type
342769419bafSAndrew Jeffery        #  to the newly enabled server type
342869419bafSAndrew Jeffery        #  Disable the currently enabled LDAP server type. Unless
342969419bafSAndrew Jeffery        #  it is disabled, we cannot enable a new LDAP server type
343069419bafSAndrew Jeffery        if (serverTypeEnabled is not None):
343169419bafSAndrew Jeffery
343269419bafSAndrew Jeffery            if (serverTypeToBeEnabled != serverTypeEnabled):
343369419bafSAndrew Jeffery                res = syncRoleMap(host,args,session,serverTypeEnabled,serverTypeToBeEnabled)
343469419bafSAndrew Jeffery
343569419bafSAndrew Jeffery            data = "{\"data\": 0 }"
343669419bafSAndrew Jeffery            res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
343769419bafSAndrew Jeffery
343869419bafSAndrew Jeffery        data = {"data": args.baseDN}
343969419bafSAndrew Jeffery        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBaseDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
344069419bafSAndrew Jeffery        if (res.status_code != requests.codes.ok):
344169419bafSAndrew Jeffery            print("Updates to the property LDAPBaseDN failed...")
344269419bafSAndrew Jeffery            return(res.text)
344369419bafSAndrew Jeffery
344469419bafSAndrew Jeffery        data = {"data": args.bindDN}
344569419bafSAndrew Jeffery        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDN', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
344669419bafSAndrew Jeffery        if (res.status_code != requests.codes.ok):
344769419bafSAndrew Jeffery           print("Updates to the property LDAPBindDN failed...")
344869419bafSAndrew Jeffery           return(res.text)
344969419bafSAndrew Jeffery
345069419bafSAndrew Jeffery        data = {"data": args.bindPassword}
345169419bafSAndrew Jeffery        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPBindDNPassword', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
345269419bafSAndrew Jeffery        if (res.status_code != requests.codes.ok):
345369419bafSAndrew Jeffery           print("Updates to the property LDAPBindDNPassword failed...")
345469419bafSAndrew Jeffery           return(res.text)
345569419bafSAndrew Jeffery
345669419bafSAndrew Jeffery        data = {"data": scope[args.scope]}
345769419bafSAndrew Jeffery        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPSearchScope', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
345869419bafSAndrew Jeffery        if (res.status_code != requests.codes.ok):
345969419bafSAndrew Jeffery           print("Updates to the property LDAPSearchScope failed...")
346069419bafSAndrew Jeffery           return(res.text)
346169419bafSAndrew Jeffery
346269419bafSAndrew Jeffery        data = {"data": args.uri}
346369419bafSAndrew Jeffery        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/LDAPServerURI', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
346469419bafSAndrew Jeffery        if (res.status_code != requests.codes.ok):
346569419bafSAndrew Jeffery           print("Updates to the property LDAPServerURI failed...")
346669419bafSAndrew Jeffery           return(res.text)
346769419bafSAndrew Jeffery
346869419bafSAndrew Jeffery        data = {"data": args.groupAttrName}
346969419bafSAndrew Jeffery        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/GroupNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
347069419bafSAndrew Jeffery        if (res.status_code != requests.codes.ok):
347169419bafSAndrew Jeffery           print("Updates to the property GroupNameAttribute failed...")
347269419bafSAndrew Jeffery           return(res.text)
347369419bafSAndrew Jeffery
347469419bafSAndrew Jeffery        data = {"data": args.userAttrName}
347569419bafSAndrew Jeffery        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/UserNameAttribute', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
347669419bafSAndrew Jeffery        if (res.status_code != requests.codes.ok):
347769419bafSAndrew Jeffery           print("Updates to the property UserNameAttribute failed...")
347869419bafSAndrew Jeffery           return(res.text)
347969419bafSAndrew Jeffery
348069419bafSAndrew Jeffery        #After updating the properties, enable the new server type
348169419bafSAndrew Jeffery        data = "{\"data\": 1 }"
348269419bafSAndrew Jeffery        res = session.put(url + serverTypeMap[serverTypeToBeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
348369419bafSAndrew Jeffery
348469419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
348569419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
348669419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
348769419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
348869419bafSAndrew Jeffery    return res.text
348969419bafSAndrew Jeffery
349069419bafSAndrew Jefferydef disableLDAP(host, args, session):
349169419bafSAndrew Jeffery    """
349269419bafSAndrew Jeffery         Called by the ldap function. Deletes the LDAP Configuration.
349369419bafSAndrew Jeffery
349469419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
349569419bafSAndrew Jeffery         @param args: contains additional arguments used by the ldap subcommand
349669419bafSAndrew Jeffery         @param session: the active session to use
349769419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output
349869419bafSAndrew Jeffery            will be provided in json format for programmatic consumption
349969419bafSAndrew Jeffery    """
350069419bafSAndrew Jeffery
350169419bafSAndrew Jeffery    try:
350269419bafSAndrew Jeffery        if (isRedfishSupport) :
350369419bafSAndrew Jeffery
350469419bafSAndrew Jeffery            url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
350569419bafSAndrew Jeffery
350669419bafSAndrew Jeffery            serverTypeEnabled = getLDAPTypeEnabled(host,session)
350769419bafSAndrew Jeffery
350869419bafSAndrew Jeffery            if (serverTypeEnabled is not None):
350969419bafSAndrew Jeffery                #To keep the role map in sync,
351069419bafSAndrew Jeffery                #If the server type being disabled has role map, then
351169419bafSAndrew Jeffery                #   - copy the role map to the other server type(s)
351269419bafSAndrew Jeffery                for serverType in serverTypeMap.keys():
351369419bafSAndrew Jeffery                    if (serverType != serverTypeEnabled):
351469419bafSAndrew Jeffery                        res = syncRoleMap(host,args,session,serverTypeEnabled,serverType)
351569419bafSAndrew Jeffery
351669419bafSAndrew Jeffery                #Disable the currently enabled LDAP server type
351769419bafSAndrew Jeffery                data = "{\"data\": 0 }"
351869419bafSAndrew Jeffery                res = session.put(url + serverTypeMap[serverTypeEnabled] + '/attr/Enabled', headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
351969419bafSAndrew Jeffery
352069419bafSAndrew Jeffery            else:
352169419bafSAndrew Jeffery                return("LDAP server has not been enabled...")
352269419bafSAndrew Jeffery
352369419bafSAndrew Jeffery        else :
352469419bafSAndrew Jeffery            url='https://'+host+'/xyz/openbmc_project/user/ldap/config/action/delete'
352569419bafSAndrew Jeffery            data = {"data": []}
352669419bafSAndrew Jeffery            res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
352769419bafSAndrew Jeffery
352869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
352969419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
353069419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
353169419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
353269419bafSAndrew Jeffery
353369419bafSAndrew Jeffery    return res.text
353469419bafSAndrew Jeffery
353569419bafSAndrew Jefferydef enableDHCP(host, args, session):
353669419bafSAndrew Jeffery
353769419bafSAndrew Jeffery    """
353869419bafSAndrew Jeffery        Called by the network function. Enables DHCP.
353969419bafSAndrew Jeffery
354069419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
354169419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
354269419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
354369419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
354469419bafSAndrew Jeffery        @param session: the active session to use
354569419bafSAndrew Jeffery    """
354669419bafSAndrew Jeffery
354769419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
354869419bafSAndrew Jeffery    "/attr/DHCPEnabled"
354969419bafSAndrew Jeffery    data = "{\"data\": 1 }"
355069419bafSAndrew Jeffery    try:
355169419bafSAndrew Jeffery        res = session.put(url, headers=jsonHeader, data=data, verify=False,
355269419bafSAndrew Jeffery                          timeout=baseTimeout)
355369419bafSAndrew Jeffery
355469419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
355569419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
355669419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
355769419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
355869419bafSAndrew Jeffery    if res.status_code == 403:
355969419bafSAndrew Jeffery        return "The specified Interface"+"("+args.Interface+")"+\
356069419bafSAndrew Jeffery        " doesn't exist"
356169419bafSAndrew Jeffery
356269419bafSAndrew Jeffery    return res.text
356369419bafSAndrew Jeffery
356469419bafSAndrew Jeffery
356569419bafSAndrew Jefferydef disableDHCP(host, args, session):
356669419bafSAndrew Jeffery    """
356769419bafSAndrew Jeffery        Called by the network function. Disables DHCP.
356869419bafSAndrew Jeffery
356969419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
357069419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
357169419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
357269419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
357369419bafSAndrew Jeffery        @param session: the active session to use
357469419bafSAndrew Jeffery    """
357569419bafSAndrew Jeffery
357669419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
357769419bafSAndrew Jeffery    "/attr/DHCPEnabled"
357869419bafSAndrew Jeffery    data = "{\"data\": 0 }"
357969419bafSAndrew Jeffery    try:
358069419bafSAndrew Jeffery        res = session.put(url, headers=jsonHeader, data=data, verify=False,
358169419bafSAndrew Jeffery                          timeout=baseTimeout)
358269419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
358369419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
358469419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
358569419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
358669419bafSAndrew Jeffery    if res.status_code == 403:
358769419bafSAndrew Jeffery        return "The specified Interface"+"("+args.Interface+")"+\
358869419bafSAndrew Jeffery        " doesn't exist"
358969419bafSAndrew Jeffery    return res.text
359069419bafSAndrew Jeffery
359169419bafSAndrew Jeffery
359269419bafSAndrew Jefferydef getHostname(host, args, session):
359369419bafSAndrew Jeffery
359469419bafSAndrew Jeffery    """
359569419bafSAndrew Jeffery        Called by the network function. Prints out the Hostname.
359669419bafSAndrew Jeffery
359769419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
359869419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
359969419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
360069419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
360169419bafSAndrew Jeffery        @param session: the active session to use
360269419bafSAndrew Jeffery    """
360369419bafSAndrew Jeffery
360469419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
360569419bafSAndrew Jeffery
360669419bafSAndrew Jeffery    try:
360769419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
360869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
360969419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
361069419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
361169419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
361269419bafSAndrew Jeffery
361369419bafSAndrew Jeffery    return res.text
361469419bafSAndrew Jeffery
361569419bafSAndrew Jeffery
361669419bafSAndrew Jefferydef setHostname(host, args, session):
361769419bafSAndrew Jeffery    """
361869419bafSAndrew Jeffery        Called by the network function. Sets the Hostname.
361969419bafSAndrew Jeffery
362069419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
362169419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
362269419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
362369419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
362469419bafSAndrew Jeffery        @param session: the active session to use
362569419bafSAndrew Jeffery    """
362669419bafSAndrew Jeffery
362769419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/network/config/attr/HostName"
362869419bafSAndrew Jeffery
362969419bafSAndrew Jeffery    data = {"data": args.HostName}
363069419bafSAndrew Jeffery
363169419bafSAndrew Jeffery    try:
363269419bafSAndrew Jeffery        res = session.put(url, headers=jsonHeader, json=data, verify=False,
363369419bafSAndrew Jeffery                          timeout=baseTimeout)
363469419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
363569419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
363669419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
363769419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
363869419bafSAndrew Jeffery
363969419bafSAndrew Jeffery    return res.text
364069419bafSAndrew Jeffery
364169419bafSAndrew Jeffery
364269419bafSAndrew Jefferydef getDomainName(host, args, session):
364369419bafSAndrew Jeffery
364469419bafSAndrew Jeffery    """
364569419bafSAndrew Jeffery        Called by the network function. Prints out the DomainName.
364669419bafSAndrew Jeffery
364769419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
364869419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
364969419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
365069419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
365169419bafSAndrew Jeffery        @param session: the active session to use
365269419bafSAndrew Jeffery    """
365369419bafSAndrew Jeffery
365469419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
365569419bafSAndrew Jeffery    "/attr/DomainName"
365669419bafSAndrew Jeffery
365769419bafSAndrew Jeffery    try:
365869419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
365969419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
366069419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
366169419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
366269419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
366369419bafSAndrew Jeffery    if res.status_code == 404:
366469419bafSAndrew Jeffery        return "The DomainName is not configured on Interface"+"("+args.Interface+")"
366569419bafSAndrew Jeffery
366669419bafSAndrew Jeffery    return res.text
366769419bafSAndrew Jeffery
366869419bafSAndrew Jeffery
366969419bafSAndrew Jefferydef setDomainName(host, args, session):
367069419bafSAndrew Jeffery    """
367169419bafSAndrew Jeffery        Called by the network function. Sets the DomainName.
367269419bafSAndrew Jeffery
367369419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
367469419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
367569419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
367669419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
367769419bafSAndrew Jeffery        @param session: the active session to use
367869419bafSAndrew Jeffery    """
367969419bafSAndrew Jeffery
368069419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
368169419bafSAndrew Jeffery    "/attr/DomainName"
368269419bafSAndrew Jeffery
368369419bafSAndrew Jeffery    data = {"data": args.DomainName.split(",")}
368469419bafSAndrew Jeffery
368569419bafSAndrew Jeffery    try:
368669419bafSAndrew Jeffery        res = session.put(url, headers=jsonHeader, json=data, verify=False,
368769419bafSAndrew Jeffery                          timeout=baseTimeout)
368869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
368969419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
369069419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
369169419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
369269419bafSAndrew Jeffery    if res.status_code == 403:
369369419bafSAndrew Jeffery        return "Failed to set Domain Name"
369469419bafSAndrew Jeffery
369569419bafSAndrew Jeffery    return res.text
369669419bafSAndrew Jeffery
369769419bafSAndrew Jeffery
369869419bafSAndrew Jefferydef getMACAddress(host, args, session):
369969419bafSAndrew Jeffery
370069419bafSAndrew Jeffery    """
370169419bafSAndrew Jeffery        Called by the network function. Prints out the MACAddress.
370269419bafSAndrew Jeffery
370369419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
370469419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
370569419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
370669419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
370769419bafSAndrew Jeffery        @param session: the active session to use
370869419bafSAndrew Jeffery    """
370969419bafSAndrew Jeffery
371069419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
371169419bafSAndrew Jeffery    "/attr/MACAddress"
371269419bafSAndrew Jeffery
371369419bafSAndrew Jeffery    try:
371469419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
371569419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
371669419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
371769419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
371869419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
371969419bafSAndrew Jeffery    if res.status_code == 404:
372069419bafSAndrew Jeffery        return "Failed to get MACAddress"
372169419bafSAndrew Jeffery
372269419bafSAndrew Jeffery    return res.text
372369419bafSAndrew Jeffery
372469419bafSAndrew Jeffery
372569419bafSAndrew Jefferydef setMACAddress(host, args, session):
372669419bafSAndrew Jeffery    """
372769419bafSAndrew Jeffery        Called by the network function. Sets the MACAddress.
372869419bafSAndrew Jeffery
372969419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
373069419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
373169419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
373269419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
373369419bafSAndrew Jeffery        @param session: the active session to use
373469419bafSAndrew Jeffery    """
373569419bafSAndrew Jeffery
373669419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/network/"+args.Interface+\
373769419bafSAndrew Jeffery    "/attr/MACAddress"
373869419bafSAndrew Jeffery
373969419bafSAndrew Jeffery    data = {"data": args.MACAddress}
374069419bafSAndrew Jeffery
374169419bafSAndrew Jeffery    try:
374269419bafSAndrew Jeffery        res = session.put(url, headers=jsonHeader, json=data, verify=False,
374369419bafSAndrew Jeffery                          timeout=baseTimeout)
374469419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
374569419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
374669419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
374769419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
374869419bafSAndrew Jeffery    if res.status_code == 403:
374969419bafSAndrew Jeffery        return "Failed to set MACAddress"
375069419bafSAndrew Jeffery
375169419bafSAndrew Jeffery    return res.text
375269419bafSAndrew Jeffery
375369419bafSAndrew Jeffery
375469419bafSAndrew Jefferydef getDefaultGateway(host, args, session):
375569419bafSAndrew Jeffery
375669419bafSAndrew Jeffery    """
375769419bafSAndrew Jeffery        Called by the network function. Prints out the DefaultGateway.
375869419bafSAndrew Jeffery
375969419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
376069419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
376169419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
376269419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
376369419bafSAndrew Jeffery        @param session: the active session to use
376469419bafSAndrew Jeffery    """
376569419bafSAndrew Jeffery
376669419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
376769419bafSAndrew Jeffery
376869419bafSAndrew Jeffery    try:
376969419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
377069419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
377169419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
377269419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
377369419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
377469419bafSAndrew Jeffery    if res.status_code == 404:
377569419bafSAndrew Jeffery        return "Failed to get Default Gateway info"
377669419bafSAndrew Jeffery
377769419bafSAndrew Jeffery    return res.text
377869419bafSAndrew Jeffery
377969419bafSAndrew Jeffery
378069419bafSAndrew Jefferydef setDefaultGateway(host, args, session):
378169419bafSAndrew Jeffery    """
378269419bafSAndrew Jeffery        Called by the network function. Sets the DefaultGateway.
378369419bafSAndrew Jeffery
378469419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
378569419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
378669419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
378769419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
378869419bafSAndrew Jeffery        @param session: the active session to use
378969419bafSAndrew Jeffery    """
379069419bafSAndrew Jeffery
379169419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/network/config/attr/DefaultGateway"
379269419bafSAndrew Jeffery
379369419bafSAndrew Jeffery    data = {"data": args.DefaultGW}
379469419bafSAndrew Jeffery
379569419bafSAndrew Jeffery    try:
379669419bafSAndrew Jeffery        res = session.put(url, headers=jsonHeader, json=data, verify=False,
379769419bafSAndrew Jeffery                          timeout=baseTimeout)
379869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
379969419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
380069419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
380169419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
380269419bafSAndrew Jeffery    if res.status_code == 403:
380369419bafSAndrew Jeffery        return "Failed to set Default Gateway"
380469419bafSAndrew Jeffery
380569419bafSAndrew Jeffery    return res.text
380669419bafSAndrew Jeffery
380769419bafSAndrew Jeffery
380869419bafSAndrew Jefferydef viewNWConfig(host, args, session):
380969419bafSAndrew Jeffery    """
381069419bafSAndrew Jeffery         Called by the ldap function. Prints out network configured properties
381169419bafSAndrew Jeffery
381269419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
381369419bafSAndrew Jeffery         @param args: contains additional arguments used by the ldap subcommand
381469419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
381569419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
381669419bafSAndrew Jeffery         @param session: the active session to use
381769419bafSAndrew Jeffery         @return returns LDAP's configured properties.
381869419bafSAndrew Jeffery    """
381969419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/network/enumerate"
382069419bafSAndrew Jeffery    try:
382169419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
382269419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
382369419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
382469419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
382569419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
382669419bafSAndrew Jeffery    except(requests.exceptions.RequestException) as err:
382769419bafSAndrew Jeffery        return connectionErrHandler(args.json, "RequestException", err)
382869419bafSAndrew Jeffery    if res.status_code == 404:
382969419bafSAndrew Jeffery        return "LDAP server config has not been created"
383069419bafSAndrew Jeffery    return res.text
383169419bafSAndrew Jeffery
383269419bafSAndrew Jeffery
383369419bafSAndrew Jefferydef getDNS(host, args, session):
383469419bafSAndrew Jeffery
383569419bafSAndrew Jeffery    """
383669419bafSAndrew Jeffery        Called by the network function. Prints out DNS servers on the interface
383769419bafSAndrew Jeffery
383869419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
383969419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
384069419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
384169419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
384269419bafSAndrew Jeffery        @param session: the active session to use
384369419bafSAndrew Jeffery    """
384469419bafSAndrew Jeffery
384569419bafSAndrew Jeffery    url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
384669419bafSAndrew Jeffery        + "/attr/Nameservers"
384769419bafSAndrew Jeffery
384869419bafSAndrew Jeffery    try:
384969419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
385069419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
385169419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
385269419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
385369419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
385469419bafSAndrew Jeffery    if res.status_code == 404:
385569419bafSAndrew Jeffery        return "The NameServer is not configured on Interface"+"("+args.Interface+")"
385669419bafSAndrew Jeffery
385769419bafSAndrew Jeffery    return res.text
385869419bafSAndrew Jeffery
385969419bafSAndrew Jeffery
386069419bafSAndrew Jefferydef setDNS(host, args, session):
386169419bafSAndrew Jeffery    """
386269419bafSAndrew Jeffery        Called by the network function. Sets DNS servers on the interface.
386369419bafSAndrew Jeffery
386469419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
386569419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
386669419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
386769419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
386869419bafSAndrew Jeffery        @param session: the active session to use
386969419bafSAndrew Jeffery    """
387069419bafSAndrew Jeffery
387169419bafSAndrew Jeffery    url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
387269419bafSAndrew Jeffery        + "/attr/Nameservers"
387369419bafSAndrew Jeffery
387469419bafSAndrew Jeffery    data = {"data": args.DNSServers.split(",")}
387569419bafSAndrew Jeffery
387669419bafSAndrew Jeffery    try:
387769419bafSAndrew Jeffery        res = session.put(url, headers=jsonHeader, json=data, verify=False,
387869419bafSAndrew Jeffery                          timeout=baseTimeout)
387969419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
388069419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
388169419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
388269419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
388369419bafSAndrew Jeffery    if res.status_code == 403:
388469419bafSAndrew Jeffery        return "Failed to set DNS"
388569419bafSAndrew Jeffery
388669419bafSAndrew Jeffery    return res.text
388769419bafSAndrew Jeffery
388869419bafSAndrew Jeffery
388969419bafSAndrew Jefferydef getNTP(host, args, session):
389069419bafSAndrew Jeffery
389169419bafSAndrew Jeffery    """
389269419bafSAndrew Jeffery        Called by the network function. Prints out NTP servers on the interface
389369419bafSAndrew Jeffery
389469419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
389569419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
389669419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
389769419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
389869419bafSAndrew Jeffery        @param session: the active session to use
389969419bafSAndrew Jeffery    """
390069419bafSAndrew Jeffery
390169419bafSAndrew Jeffery    url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
390269419bafSAndrew Jeffery        + "/attr/NTPServers"
390369419bafSAndrew Jeffery    try:
390469419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
390569419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
390669419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
390769419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
390869419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
390969419bafSAndrew Jeffery    if res.status_code == 404:
391069419bafSAndrew Jeffery        return "The NTPServer is not configured on Interface"+"("+args.Interface+")"
391169419bafSAndrew Jeffery
391269419bafSAndrew Jeffery    return res.text
391369419bafSAndrew Jeffery
391469419bafSAndrew Jeffery
391569419bafSAndrew Jefferydef setNTP(host, args, session):
391669419bafSAndrew Jeffery    """
391769419bafSAndrew Jeffery        Called by the network function. Sets NTP servers on the interface.
391869419bafSAndrew Jeffery
391969419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
392069419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
392169419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
392269419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
392369419bafSAndrew Jeffery        @param session: the active session to use
392469419bafSAndrew Jeffery    """
392569419bafSAndrew Jeffery
392669419bafSAndrew Jeffery    url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
392769419bafSAndrew Jeffery        + "/attr/NTPServers"
392869419bafSAndrew Jeffery
392969419bafSAndrew Jeffery    data = {"data": args.NTPServers.split(",")}
393069419bafSAndrew Jeffery
393169419bafSAndrew Jeffery    try:
393269419bafSAndrew Jeffery        res = session.put(url, headers=jsonHeader, json=data, verify=False,
393369419bafSAndrew Jeffery                          timeout=baseTimeout)
393469419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
393569419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
393669419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
393769419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
393869419bafSAndrew Jeffery    if res.status_code == 403:
393969419bafSAndrew Jeffery        return "Failed to set NTP"
394069419bafSAndrew Jeffery
394169419bafSAndrew Jeffery    return res.text
394269419bafSAndrew Jeffery
394369419bafSAndrew Jeffery
394469419bafSAndrew Jefferydef addIP(host, args, session):
394569419bafSAndrew Jeffery    """
394669419bafSAndrew Jeffery        Called by the network function. Configures IP address on given interface
394769419bafSAndrew Jeffery
394869419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
394969419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
395069419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
395169419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
395269419bafSAndrew Jeffery        @param session: the active session to use
395369419bafSAndrew Jeffery    """
395469419bafSAndrew Jeffery
395569419bafSAndrew Jeffery    url = "https://" + host + "/xyz/openbmc_project/network/" + args.Interface\
395669419bafSAndrew Jeffery        + "/action/IP"
395769419bafSAndrew Jeffery    protocol = {
395869419bafSAndrew Jeffery             'ipv4': 'xyz.openbmc_project.Network.IP.Protocol.IPv4',
395969419bafSAndrew Jeffery             'ipv6': 'xyz.openbmc_project.Network.IP.Protocol.IPv6'
396069419bafSAndrew Jeffery            }
396169419bafSAndrew Jeffery
396269419bafSAndrew Jeffery    data = {"data": [protocol[args.type], args.address, int(args.prefixLength),
396369419bafSAndrew Jeffery        args.gateway]}
396469419bafSAndrew Jeffery
396569419bafSAndrew Jeffery    try:
396669419bafSAndrew Jeffery        res = session.post(url, headers=jsonHeader, json=data, verify=False,
396769419bafSAndrew Jeffery                           timeout=baseTimeout)
396869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
396969419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
397069419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
397169419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
397269419bafSAndrew Jeffery    if res.status_code == 404:
397369419bafSAndrew Jeffery        return "The specified Interface" + "(" + args.Interface + ")" +\
397469419bafSAndrew Jeffery            " doesn't exist"
397569419bafSAndrew Jeffery
397669419bafSAndrew Jeffery    return res.text
397769419bafSAndrew Jeffery
397869419bafSAndrew Jeffery
397969419bafSAndrew Jefferydef getIP(host, args, session):
398069419bafSAndrew Jeffery    """
398169419bafSAndrew Jeffery        Called by the network function. Prints out IP address of given interface
398269419bafSAndrew Jeffery
398369419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
398469419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
398569419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
398669419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
398769419bafSAndrew Jeffery        @param session: the active session to use
398869419bafSAndrew Jeffery    """
398969419bafSAndrew Jeffery
399069419bafSAndrew Jeffery    url = "https://" + host+"/xyz/openbmc_project/network/" + args.Interface +\
399169419bafSAndrew Jeffery        "/enumerate"
399269419bafSAndrew Jeffery    try:
399369419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
399469419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
399569419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
399669419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
399769419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
399869419bafSAndrew Jeffery    if res.status_code == 404:
399969419bafSAndrew Jeffery        return "The specified Interface" + "(" + args.Interface + ")" +\
400069419bafSAndrew Jeffery            " doesn't exist"
400169419bafSAndrew Jeffery
400269419bafSAndrew Jeffery    return res.text
400369419bafSAndrew Jeffery
400469419bafSAndrew Jeffery
400569419bafSAndrew Jefferydef deleteIP(host, args, session):
400669419bafSAndrew Jeffery    """
400769419bafSAndrew Jeffery        Called by the network function. Deletes the IP address from given Interface
400869419bafSAndrew Jeffery
400969419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
401069419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
401169419bafSAndrew Jeffery        @param session: the active session to use
401269419bafSAndrew Jeffery        @param args.json: boolean, if this flag is set to true, the output
401369419bafSAndrew Jeffery            will be provided in json format for programmatic consumption
401469419bafSAndrew Jeffery    """
401569419bafSAndrew Jeffery
401669419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/network/" + args.Interface+\
401769419bafSAndrew Jeffery        "/enumerate"
401869419bafSAndrew Jeffery    data = {"data": []}
401969419bafSAndrew Jeffery    try:
402069419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
402169419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
402269419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
402369419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
402469419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
402569419bafSAndrew Jeffery    if res.status_code == 404:
402669419bafSAndrew Jeffery        return "The specified Interface" + "(" + args.Interface + ")" +\
402769419bafSAndrew Jeffery            " doesn't exist"
402869419bafSAndrew Jeffery    objDict = json.loads(res.text)
402969419bafSAndrew Jeffery    if not objDict['data']:
403069419bafSAndrew Jeffery        return "No object found for given address on given Interface"
403169419bafSAndrew Jeffery    for obj in objDict['data']:
403269419bafSAndrew Jeffery        try:
403369419bafSAndrew Jeffery            if args.address in objDict['data'][obj]['Address']:
403469419bafSAndrew Jeffery                url = "https://"+host+obj+"/action/Delete"
403569419bafSAndrew Jeffery                try:
403669419bafSAndrew Jeffery                    res = session.post(url, headers=jsonHeader, json=data,
403769419bafSAndrew Jeffery                                       verify=False, timeout=baseTimeout)
403869419bafSAndrew Jeffery                except(requests.exceptions.Timeout):
403969419bafSAndrew Jeffery                    return(connectionErrHandler(args.json, "Timeout", None))
404069419bafSAndrew Jeffery                except(requests.exceptions.ConnectionError) as err:
404169419bafSAndrew Jeffery                    return connectionErrHandler(args.json, "ConnectionError", err)
404269419bafSAndrew Jeffery                return res.text
404369419bafSAndrew Jeffery            else:
404469419bafSAndrew Jeffery                continue
404569419bafSAndrew Jeffery        except KeyError:
404669419bafSAndrew Jeffery            continue
404769419bafSAndrew Jeffery    return "No object found for address " + args.address + \
404869419bafSAndrew Jeffery           " on Interface(" + args.Interface + ")"
404969419bafSAndrew Jeffery
405069419bafSAndrew Jeffery
405169419bafSAndrew Jefferydef addVLAN(host, args, session):
405269419bafSAndrew Jeffery    """
405369419bafSAndrew Jeffery        Called by the network function. Creates VLAN on given interface.
405469419bafSAndrew Jeffery
405569419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
405669419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
405769419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
405869419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
405969419bafSAndrew Jeffery        @param session: the active session to use
406069419bafSAndrew Jeffery    """
406169419bafSAndrew Jeffery
406269419bafSAndrew Jeffery    url = "https://" + host+"/xyz/openbmc_project/network/action/VLAN"
406369419bafSAndrew Jeffery
406469419bafSAndrew Jeffery    data = {"data": [args.Interface,int(args.Identifier)]}
406569419bafSAndrew Jeffery    try:
406669419bafSAndrew Jeffery        res = session.post(url, headers=jsonHeader, json=data, verify=False,
406769419bafSAndrew Jeffery                           timeout=baseTimeout)
406869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
406969419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
407069419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
407169419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
407269419bafSAndrew Jeffery    if res.status_code == 400:
407369419bafSAndrew Jeffery        return "Adding VLAN to interface" + "(" + args.Interface + ")" +\
407469419bafSAndrew Jeffery            " failed"
407569419bafSAndrew Jeffery
407669419bafSAndrew Jeffery    return res.text
407769419bafSAndrew Jeffery
407869419bafSAndrew Jeffery
407969419bafSAndrew Jefferydef deleteVLAN(host, args, session):
408069419bafSAndrew Jeffery    """
408169419bafSAndrew Jeffery        Called by the network function. Creates VLAN on given interface.
408269419bafSAndrew Jeffery
408369419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
408469419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
408569419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
408669419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
408769419bafSAndrew Jeffery        @param session: the active session to use
408869419bafSAndrew Jeffery    """
408969419bafSAndrew Jeffery
409069419bafSAndrew Jeffery    url = "https://" + host+"/xyz/openbmc_project/network/"+args.Interface+"/action/Delete"
409169419bafSAndrew Jeffery    data = {"data": []}
409269419bafSAndrew Jeffery
409369419bafSAndrew Jeffery    try:
409469419bafSAndrew Jeffery        res = session.post(url, headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
409569419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
409669419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
409769419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
409869419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
409969419bafSAndrew Jeffery    if res.status_code == 404:
410069419bafSAndrew Jeffery        return "The specified VLAN"+"("+args.Interface+")" +" doesn't exist"
410169419bafSAndrew Jeffery
410269419bafSAndrew Jeffery    return res.text
410369419bafSAndrew Jeffery
410469419bafSAndrew Jeffery
410569419bafSAndrew Jefferydef viewDHCPConfig(host, args, session):
410669419bafSAndrew Jeffery    """
410769419bafSAndrew Jeffery        Called by the network function. Shows DHCP configured Properties.
410869419bafSAndrew Jeffery
410969419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
411069419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
411169419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
411269419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
411369419bafSAndrew Jeffery        @param session: the active session to use
411469419bafSAndrew Jeffery    """
411569419bafSAndrew Jeffery
411669419bafSAndrew Jeffery    url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
411769419bafSAndrew Jeffery
411869419bafSAndrew Jeffery    try:
411969419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
412069419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
412169419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
412269419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
412369419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
412469419bafSAndrew Jeffery
412569419bafSAndrew Jeffery    return res.text
412669419bafSAndrew Jeffery
412769419bafSAndrew Jeffery
412869419bafSAndrew Jefferydef configureDHCP(host, args, session):
412969419bafSAndrew Jeffery    """
413069419bafSAndrew Jeffery        Called by the network function. Configures/updates DHCP Properties.
413169419bafSAndrew Jeffery
413269419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
413369419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
413469419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
413569419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
413669419bafSAndrew Jeffery        @param session: the active session to use
413769419bafSAndrew Jeffery    """
413869419bafSAndrew Jeffery
413969419bafSAndrew Jeffery
414069419bafSAndrew Jeffery    try:
414169419bafSAndrew Jeffery        url="https://"+host+"/xyz/openbmc_project/network/config/dhcp"
414269419bafSAndrew Jeffery        if(args.DNSEnabled == True):
414369419bafSAndrew Jeffery            data = '{"data": 1}'
414469419bafSAndrew Jeffery        else:
414569419bafSAndrew Jeffery            data = '{"data": 0}'
414669419bafSAndrew Jeffery        res = session.put(url + '/attr/DNSEnabled', headers=jsonHeader,
414769419bafSAndrew Jeffery                          data=data, verify=False, timeout=baseTimeout)
414869419bafSAndrew Jeffery        if(args.HostNameEnabled == True):
414969419bafSAndrew Jeffery            data = '{"data": 1}'
415069419bafSAndrew Jeffery        else:
415169419bafSAndrew Jeffery            data = '{"data": 0}'
415269419bafSAndrew Jeffery        res = session.put(url + '/attr/HostNameEnabled', headers=jsonHeader,
415369419bafSAndrew Jeffery                          data=data, verify=False, timeout=baseTimeout)
415469419bafSAndrew Jeffery        if(args.NTPEnabled == True):
415569419bafSAndrew Jeffery            data = '{"data": 1}'
415669419bafSAndrew Jeffery        else:
415769419bafSAndrew Jeffery            data = '{"data": 0}'
415869419bafSAndrew Jeffery        res = session.put(url + '/attr/NTPEnabled', headers=jsonHeader,
415969419bafSAndrew Jeffery                          data=data, verify=False, timeout=baseTimeout)
416069419bafSAndrew Jeffery        if(args.SendHostNameEnabled == True):
416169419bafSAndrew Jeffery            data = '{"data": 1}'
416269419bafSAndrew Jeffery        else:
416369419bafSAndrew Jeffery            data = '{"data": 0}'
416469419bafSAndrew Jeffery        res = session.put(url + '/attr/SendHostNameEnabled', headers=jsonHeader,
416569419bafSAndrew Jeffery                          data=data, verify=False, timeout=baseTimeout)
416669419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
416769419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
416869419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
416969419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
417069419bafSAndrew Jeffery
417169419bafSAndrew Jeffery    return res.text
417269419bafSAndrew Jeffery
417369419bafSAndrew Jeffery
417469419bafSAndrew Jefferydef nwReset(host, args, session):
417569419bafSAndrew Jeffery
417669419bafSAndrew Jeffery    """
417769419bafSAndrew Jeffery        Called by the network function. Resets networks setting to factory defaults.
417869419bafSAndrew Jeffery
417969419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
418069419bafSAndrew Jeffery        @param args: contains additional arguments used by the ldap subcommand
418169419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
418269419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
418369419bafSAndrew Jeffery        @param session: the active session to use
418469419bafSAndrew Jeffery    """
418569419bafSAndrew Jeffery
418669419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/network/action/Reset"
418769419bafSAndrew Jeffery    data = '{"data":[] }'
418869419bafSAndrew Jeffery    try:
418969419bafSAndrew Jeffery        res = session.post(url, headers=jsonHeader, data=data, verify=False,
419069419bafSAndrew Jeffery                          timeout=baseTimeout)
419169419bafSAndrew Jeffery
419269419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
419369419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
419469419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
419569419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
419669419bafSAndrew Jeffery
419769419bafSAndrew Jeffery    return res.text
419869419bafSAndrew Jeffery
419969419bafSAndrew Jefferydef getLDAPTypeEnabled(host,session):
420069419bafSAndrew Jeffery
420169419bafSAndrew Jeffery    """
420269419bafSAndrew Jeffery        Called by LDAP related functions to find the LDAP server type that has been enabled.
420369419bafSAndrew Jeffery        Returns None if LDAP has not been configured.
420469419bafSAndrew Jeffery
420569419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
420669419bafSAndrew Jeffery        @param session: the active session to use
420769419bafSAndrew Jeffery    """
420869419bafSAndrew Jeffery
420969419bafSAndrew Jeffery    enabled = False
421069419bafSAndrew Jeffery    url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
421169419bafSAndrew Jeffery    for key,value in serverTypeMap.items():
421269419bafSAndrew Jeffery        data = {"data": []}
421369419bafSAndrew Jeffery        try:
421469419bafSAndrew Jeffery            res = session.get(url + value + '/attr/Enabled', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
421569419bafSAndrew Jeffery        except(requests.exceptions.Timeout):
421669419bafSAndrew Jeffery            print(connectionErrHandler(args.json, "Timeout", None))
421769419bafSAndrew Jeffery            return
421869419bafSAndrew Jeffery        except(requests.exceptions.ConnectionError) as err:
421969419bafSAndrew Jeffery            print(connectionErrHandler(args.json, "ConnectionError", err))
422069419bafSAndrew Jeffery            return
422169419bafSAndrew Jeffery
422269419bafSAndrew Jeffery        enabled = res.json()['data']
422369419bafSAndrew Jeffery        if (enabled):
422469419bafSAndrew Jeffery            return key
422569419bafSAndrew Jeffery
422669419bafSAndrew Jefferydef syncRoleMap(host,args,session,fromServerType,toServerType):
422769419bafSAndrew Jeffery
422869419bafSAndrew Jeffery    """
422969419bafSAndrew Jeffery        Called by LDAP related functions to sync the role maps
423069419bafSAndrew Jeffery        Returns False if LDAP has not been configured.
423169419bafSAndrew Jeffery
423269419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
423369419bafSAndrew Jeffery        @param session: the active session to use
423469419bafSAndrew Jeffery        @param fromServerType : Server type whose role map has to be copied
423569419bafSAndrew Jeffery        @param toServerType : Server type to which role map has to be copied
423669419bafSAndrew Jeffery    """
423769419bafSAndrew Jeffery
423869419bafSAndrew Jeffery    url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
423969419bafSAndrew Jeffery
424069419bafSAndrew Jeffery    try:
424169419bafSAndrew Jeffery        #Note: If the fromServerType has no role map, then
424269419bafSAndrew Jeffery        #the toServerType will not have any role map.
424369419bafSAndrew Jeffery
424469419bafSAndrew Jeffery        #delete the privilege mapping from the toServerType and
424569419bafSAndrew Jeffery        #then copy the privilege mapping from fromServerType to
424669419bafSAndrew Jeffery        #toServerType.
424769419bafSAndrew Jeffery        args.serverType = toServerType
424869419bafSAndrew Jeffery        res = deleteAllPrivilegeMapping(host, args, session)
424969419bafSAndrew Jeffery
425069419bafSAndrew Jeffery        data = {"data": []}
425169419bafSAndrew Jeffery        res = session.get(url + serverTypeMap[fromServerType] + '/role_map/enumerate', headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
425269419bafSAndrew Jeffery        #Previously enabled server type has no role map
425369419bafSAndrew Jeffery        if (res.status_code != requests.codes.ok):
425469419bafSAndrew Jeffery
425569419bafSAndrew Jeffery            #fromServerType has no role map; So, no need to copy
425669419bafSAndrew Jeffery            #role map to toServerType.
425769419bafSAndrew Jeffery            return
425869419bafSAndrew Jeffery
425969419bafSAndrew Jeffery        objDict = json.loads(res.text)
426069419bafSAndrew Jeffery        dataDict = objDict['data']
426169419bafSAndrew Jeffery        for  key,value in dataDict.items():
426269419bafSAndrew Jeffery            data = {"data": [value["GroupName"], value["Privilege"]]}
426369419bafSAndrew Jeffery            res = session.post(url + serverTypeMap[toServerType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
426469419bafSAndrew Jeffery
426569419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
426669419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
426769419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
426869419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
426969419bafSAndrew Jeffery    return res.text
427069419bafSAndrew Jeffery
427169419bafSAndrew Jeffery
427269419bafSAndrew Jefferydef createPrivilegeMapping(host, args, session):
427369419bafSAndrew Jeffery    """
427469419bafSAndrew Jeffery         Called by the ldap function. Creates the group and the privilege mapping.
427569419bafSAndrew Jeffery
427669419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
427769419bafSAndrew Jeffery         @param args: contains additional arguments used by the ldap subcommand
427869419bafSAndrew Jeffery         @param session: the active session to use
427969419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output
428069419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
428169419bafSAndrew Jeffery    """
428269419bafSAndrew Jeffery
428369419bafSAndrew Jeffery    try:
428469419bafSAndrew Jeffery        if (isRedfishSupport):
428569419bafSAndrew Jeffery            url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'
428669419bafSAndrew Jeffery
428769419bafSAndrew Jeffery            #To maintain the interface compatibility between op930 and op940, the server type has been made
428869419bafSAndrew Jeffery            #optional. If the server type is not specified, then create the role-mapper for the currently
428969419bafSAndrew Jeffery            #enabled server type.
429069419bafSAndrew Jeffery            serverType = args.serverType
429169419bafSAndrew Jeffery            if (serverType is None):
429269419bafSAndrew Jeffery                serverType = getLDAPTypeEnabled(host,session)
429369419bafSAndrew Jeffery                if (serverType is None):
429469419bafSAndrew Jeffery                     return("LDAP server has not been enabled. Please specify LDAP serverType to proceed further...")
429569419bafSAndrew Jeffery
429669419bafSAndrew Jeffery            data = {"data": [args.groupName,args.privilege]}
429769419bafSAndrew Jeffery            res = session.post(url + serverTypeMap[serverType] + '/action/Create', headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
429869419bafSAndrew Jeffery
429969419bafSAndrew Jeffery        else:
430069419bafSAndrew Jeffery            url = 'https://'+host+'/xyz/openbmc_project/user/ldap/action/Create'
430169419bafSAndrew Jeffery            data = {"data": [args.groupName,args.privilege]}
430269419bafSAndrew Jeffery            res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
430369419bafSAndrew Jeffery
430469419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
430569419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
430669419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
430769419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
430869419bafSAndrew Jeffery    return res.text
430969419bafSAndrew Jeffery
431069419bafSAndrew Jefferydef listPrivilegeMapping(host, args, session):
431169419bafSAndrew Jeffery    """
431269419bafSAndrew Jeffery         Called by the ldap function. Lists the group and the privilege mapping.
431369419bafSAndrew Jeffery
431469419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
431569419bafSAndrew Jeffery         @param args: contains additional arguments used by the ldap subcommand
431669419bafSAndrew Jeffery         @param session: the active session to use
431769419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output
431869419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
431969419bafSAndrew Jeffery    """
432069419bafSAndrew Jeffery
432169419bafSAndrew Jeffery    if (isRedfishSupport):
432269419bafSAndrew Jeffery        serverType = args.serverType
432369419bafSAndrew Jeffery        if (serverType is None):
432469419bafSAndrew Jeffery            serverType = getLDAPTypeEnabled(host,session)
432569419bafSAndrew Jeffery            if (serverType is None):
432669419bafSAndrew Jeffery                return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
432769419bafSAndrew Jeffery
432869419bafSAndrew Jeffery        url = 'https://'+host+'/xyz/openbmc_project/user/ldap/'+serverTypeMap[serverType]+'/role_map/enumerate'
432969419bafSAndrew Jeffery
433069419bafSAndrew Jeffery    else:
433169419bafSAndrew Jeffery        url = 'https://'+host+'/xyz/openbmc_project/user/ldap/enumerate'
433269419bafSAndrew Jeffery
433369419bafSAndrew Jeffery    data = {"data": []}
433469419bafSAndrew Jeffery
433569419bafSAndrew Jeffery    try:
433669419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
433769419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
433869419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
433969419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
434069419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
434169419bafSAndrew Jeffery
434269419bafSAndrew Jeffery    return res.text
434369419bafSAndrew Jeffery
434469419bafSAndrew Jefferydef deletePrivilegeMapping(host, args, session):
434569419bafSAndrew Jeffery    """
434669419bafSAndrew Jeffery         Called by the ldap function. Deletes the mapping associated with the group.
434769419bafSAndrew Jeffery
434869419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
434969419bafSAndrew Jeffery         @param args: contains additional arguments used by the ldap subcommand
435069419bafSAndrew Jeffery         @param session: the active session to use
435169419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output
435269419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
435369419bafSAndrew Jeffery    """
435469419bafSAndrew Jeffery
435569419bafSAndrew Jeffery    ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
435669419bafSAndrew Jeffery    ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
435769419bafSAndrew Jeffery    path = ''
435869419bafSAndrew Jeffery    data = {"data": []}
435969419bafSAndrew Jeffery
436069419bafSAndrew Jeffery    if (isRedfishSupport):
436169419bafSAndrew Jeffery        if (args.serverType is None):
436269419bafSAndrew Jeffery            serverType = getLDAPTypeEnabled(host,session)
436369419bafSAndrew Jeffery            if (serverType is None):
436469419bafSAndrew Jeffery                return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
436569419bafSAndrew Jeffery        # search for the object having the mapping for the given group
436669419bafSAndrew Jeffery        for key,value in ldapNameSpaceObjects.items():
436769419bafSAndrew Jeffery            if value['GroupName'] == args.groupName:
436869419bafSAndrew Jeffery                path = key
436969419bafSAndrew Jeffery                break
437069419bafSAndrew Jeffery
437169419bafSAndrew Jeffery        if path == '':
437269419bafSAndrew Jeffery            return "No privilege mapping found for this group."
437369419bafSAndrew Jeffery
437469419bafSAndrew Jeffery        # delete the object
437569419bafSAndrew Jeffery        url = 'https://'+host+path+'/action/Delete'
437669419bafSAndrew Jeffery
437769419bafSAndrew Jeffery    else:
437869419bafSAndrew Jeffery        # not interested in the config objet
437969419bafSAndrew Jeffery        ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
438069419bafSAndrew Jeffery
438169419bafSAndrew Jeffery        # search for the object having the mapping for the given group
438269419bafSAndrew Jeffery        for key,value in ldapNameSpaceObjects.items():
438369419bafSAndrew Jeffery            if value['GroupName'] == args.groupName:
438469419bafSAndrew Jeffery                path = key
438569419bafSAndrew Jeffery                break
438669419bafSAndrew Jeffery
438769419bafSAndrew Jeffery        if path == '':
438869419bafSAndrew Jeffery            return "No privilege mapping found for this group."
438969419bafSAndrew Jeffery
439069419bafSAndrew Jeffery        # delete the object
439169419bafSAndrew Jeffery        url = 'https://'+host+path+'/action/delete'
439269419bafSAndrew Jeffery
439369419bafSAndrew Jeffery    try:
439469419bafSAndrew Jeffery        res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
439569419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
439669419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
439769419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
439869419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
439969419bafSAndrew Jeffery    return res.text
440069419bafSAndrew Jeffery
440169419bafSAndrew Jefferydef deleteAllPrivilegeMapping(host, args, session):
440269419bafSAndrew Jeffery    """
440369419bafSAndrew Jeffery         Called by the ldap function. Deletes all the privilege mapping and group defined.
440469419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
440569419bafSAndrew Jeffery         @param args: contains additional arguments used by the ldap subcommand
440669419bafSAndrew Jeffery         @param session: the active session to use
440769419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output
440869419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
440969419bafSAndrew Jeffery    """
441069419bafSAndrew Jeffery
441169419bafSAndrew Jeffery    ldapNameSpaceObjects = listPrivilegeMapping(host, args, session)
441269419bafSAndrew Jeffery    ldapNameSpaceObjects = json.loads(ldapNameSpaceObjects)["data"]
441369419bafSAndrew Jeffery    path = ''
441469419bafSAndrew Jeffery    data = {"data": []}
441569419bafSAndrew Jeffery
441669419bafSAndrew Jeffery    if (isRedfishSupport):
441769419bafSAndrew Jeffery        if (args.serverType is None):
441869419bafSAndrew Jeffery            serverType = getLDAPTypeEnabled(host,session)
441969419bafSAndrew Jeffery            if (serverType is None):
442069419bafSAndrew Jeffery                return("LDAP has not been enabled. Please specify LDAP serverType to proceed further...")
442169419bafSAndrew Jeffery
442269419bafSAndrew Jeffery    else:
442369419bafSAndrew Jeffery        # Remove the config object.
442469419bafSAndrew Jeffery        ldapNameSpaceObjects.pop('/xyz/openbmc_project/user/ldap/config', None)
442569419bafSAndrew Jeffery
442669419bafSAndrew Jeffery    try:
442769419bafSAndrew Jeffery        # search for GroupName property and delete if it is available.
442869419bafSAndrew Jeffery        for path in ldapNameSpaceObjects.keys():
442969419bafSAndrew Jeffery            # delete the object
443069419bafSAndrew Jeffery            url = 'https://'+host+path+'/action/Delete'
443169419bafSAndrew Jeffery            res = session.post(url, headers=jsonHeader, json = data, verify=False, timeout=baseTimeout)
443269419bafSAndrew Jeffery
443369419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
443469419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
443569419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
443669419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
443769419bafSAndrew Jeffery    return res.text
443869419bafSAndrew Jeffery
443969419bafSAndrew Jefferydef viewLDAPConfig(host, args, session):
444069419bafSAndrew Jeffery    """
444169419bafSAndrew Jeffery         Called by the ldap function. Prints out active LDAP configuration properties
444269419bafSAndrew Jeffery
444369419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
444469419bafSAndrew Jeffery         @param args: contains additional arguments used by the ldap subcommand
444569419bafSAndrew Jeffery                args.json: boolean, if this flag is set to true, the output
444669419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
444769419bafSAndrew Jeffery         @param session: the active session to use
444869419bafSAndrew Jeffery         @return returns LDAP's configured properties.
444969419bafSAndrew Jeffery    """
445069419bafSAndrew Jeffery
445169419bafSAndrew Jeffery    try:
445269419bafSAndrew Jeffery        if (isRedfishSupport):
445369419bafSAndrew Jeffery
445469419bafSAndrew Jeffery            url = "https://"+host+"/xyz/openbmc_project/user/ldap/"
445569419bafSAndrew Jeffery
445669419bafSAndrew Jeffery            serverTypeEnabled = getLDAPTypeEnabled(host,session)
445769419bafSAndrew Jeffery
445869419bafSAndrew Jeffery            if (serverTypeEnabled is not None):
445969419bafSAndrew Jeffery                data = {"data": []}
446069419bafSAndrew Jeffery                res = session.get(url + serverTypeMap[serverTypeEnabled], headers=jsonHeader, json=data, verify=False, timeout=baseTimeout)
446169419bafSAndrew Jeffery            else:
446269419bafSAndrew Jeffery                return("LDAP server has not been enabled...")
446369419bafSAndrew Jeffery
446469419bafSAndrew Jeffery        else :
446569419bafSAndrew Jeffery            url = "https://"+host+"/xyz/openbmc_project/user/ldap/config"
446669419bafSAndrew Jeffery            res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
446769419bafSAndrew Jeffery
446869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
446969419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
447069419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
447169419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
447269419bafSAndrew Jeffery    if res.status_code == 404:
447369419bafSAndrew Jeffery        return "LDAP server config has not been created"
447469419bafSAndrew Jeffery    return res.text
447569419bafSAndrew Jeffery
447669419bafSAndrew Jefferydef str2bool(v):
447769419bafSAndrew Jeffery    if v.lower() in ('yes', 'true', 't', 'y', '1'):
447869419bafSAndrew Jeffery        return True
447969419bafSAndrew Jeffery    elif v.lower() in ('no', 'false', 'f', 'n', '0'):
448069419bafSAndrew Jeffery        return False
448169419bafSAndrew Jeffery    else:
448269419bafSAndrew Jeffery        raise argparse.ArgumentTypeError('Boolean value expected.')
448369419bafSAndrew Jeffery
448469419bafSAndrew Jefferydef localUsers(host, args, session):
448569419bafSAndrew Jeffery    """
448669419bafSAndrew Jeffery        Enables and disables local BMC users.
448769419bafSAndrew Jeffery
448869419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
448969419bafSAndrew Jeffery        @param args: contains additional arguments used by the logging sub command
449069419bafSAndrew Jeffery        @param session: the active session to use
449169419bafSAndrew Jeffery    """
449269419bafSAndrew Jeffery
449369419bafSAndrew Jeffery    url="https://{hostname}/xyz/openbmc_project/user/enumerate".format(hostname=host)
449469419bafSAndrew Jeffery    try:
449569419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=baseTimeout)
449669419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
449769419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
449869419bafSAndrew Jeffery    usersDict = json.loads(res.text)
449969419bafSAndrew Jeffery
450069419bafSAndrew Jeffery    if not usersDict['data']:
450169419bafSAndrew Jeffery        return "No users found"
450269419bafSAndrew Jeffery
450369419bafSAndrew Jeffery    output = ""
450469419bafSAndrew Jeffery    for user in usersDict['data']:
450569419bafSAndrew Jeffery
450669419bafSAndrew Jeffery        # Skip LDAP and another non-local users
450769419bafSAndrew Jeffery        if 'UserEnabled' not in usersDict['data'][user]:
450869419bafSAndrew Jeffery            continue
450969419bafSAndrew Jeffery
451069419bafSAndrew Jeffery        name = user.split('/')[-1]
451169419bafSAndrew Jeffery        url = "https://{hostname}{user}/attr/UserEnabled".format(hostname=host, user=user)
451269419bafSAndrew Jeffery
451369419bafSAndrew Jeffery        if args.local_users == "queryenabled":
451469419bafSAndrew Jeffery            try:
451569419bafSAndrew Jeffery                res = session.get(url, headers=jsonHeader,verify=False, timeout=baseTimeout)
451669419bafSAndrew Jeffery            except(requests.exceptions.Timeout):
451769419bafSAndrew Jeffery                return(connectionErrHandler(args.json, "Timeout", None))
451869419bafSAndrew Jeffery
451969419bafSAndrew Jeffery            result = json.loads(res.text)
452069419bafSAndrew Jeffery            output += ("User: {name}  Enabled: {result}\n").format(name=name, result=result['data'])
452169419bafSAndrew Jeffery
452269419bafSAndrew Jeffery        elif args.local_users in ["enableall", "disableall"]:
452369419bafSAndrew Jeffery            action = ""
452469419bafSAndrew Jeffery            if args.local_users == "enableall":
452569419bafSAndrew Jeffery                data = '{"data": true}'
452669419bafSAndrew Jeffery                action = "Enabling"
452769419bafSAndrew Jeffery            else:
452869419bafSAndrew Jeffery                data = '{"data": false}'
452969419bafSAndrew Jeffery                action = "Disabling"
453069419bafSAndrew Jeffery
453169419bafSAndrew Jeffery            output += "{action} {name}\n".format(action=action, name=name)
453269419bafSAndrew Jeffery
453369419bafSAndrew Jeffery            try:
453469419bafSAndrew Jeffery                resp = session.put(url, headers=jsonHeader, data=data, verify=False, timeout=baseTimeout)
453569419bafSAndrew Jeffery            except(requests.exceptions.Timeout):
453669419bafSAndrew Jeffery                return connectionErrHandler(args.json, "Timeout", None)
453769419bafSAndrew Jeffery            except(requests.exceptions.ConnectionError) as err:
453869419bafSAndrew Jeffery                return connectionErrHandler(args.json, "ConnectionError", err)
453969419bafSAndrew Jeffery        else:
454069419bafSAndrew Jeffery            return "Invalid local users argument"
454169419bafSAndrew Jeffery
454269419bafSAndrew Jeffery    return output
454369419bafSAndrew Jeffery
454469419bafSAndrew Jefferydef setPassword(host, args, session):
454569419bafSAndrew Jeffery    """
454669419bafSAndrew Jeffery         Set local user password
454769419bafSAndrew Jeffery         @param host: string, the hostname or IP address of the bmc
454869419bafSAndrew Jeffery         @param args: contains additional arguments used by the logging sub
454969419bafSAndrew Jeffery                command
455069419bafSAndrew Jeffery         @param session: the active session to use
455169419bafSAndrew Jeffery         @param args.json: boolean, if this flag is set to true, the output
455269419bafSAndrew Jeffery                will be provided in json format for programmatic consumption
455369419bafSAndrew Jeffery         @return: Session object
455469419bafSAndrew Jeffery    """
455569419bafSAndrew Jeffery    try:
455669419bafSAndrew Jeffery        if(isRedfishSupport):
455769419bafSAndrew Jeffery            url = "https://" + host + "/redfish/v1/AccountService/Accounts/"+ \
455869419bafSAndrew Jeffery                  args.user
455969419bafSAndrew Jeffery            data = {"Password":args.password}
456069419bafSAndrew Jeffery            res = session.patch(url, headers=jsonHeader, json=data,
456169419bafSAndrew Jeffery                                verify=False, timeout=baseTimeout)
456269419bafSAndrew Jeffery        else:
456369419bafSAndrew Jeffery            url = "https://" + host + "/xyz/openbmc_project/user/" + args.user + \
456469419bafSAndrew Jeffery                "/action/SetPassword"
456569419bafSAndrew Jeffery            res = session.post(url, headers=jsonHeader,
456669419bafSAndrew Jeffery                           json={"data": [args.password]}, verify=False,
456769419bafSAndrew Jeffery                           timeout=baseTimeout)
456869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
456969419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
457069419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
457169419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
457269419bafSAndrew Jeffery    except(requests.exceptions.RequestException) as err:
457369419bafSAndrew Jeffery        return connectionErrHandler(args.json, "RequestException", err)
457469419bafSAndrew Jeffery    return res.status_code
457569419bafSAndrew Jeffery
457669419bafSAndrew Jefferydef getThermalZones(host, args, session):
457769419bafSAndrew Jeffery    """
457869419bafSAndrew Jeffery        Get the available thermal control zones
457969419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
458069419bafSAndrew Jeffery        @param args: contains additional arguments used to get the thermal
458169419bafSAndrew Jeffery               control zones
458269419bafSAndrew Jeffery        @param session: the active session to use
458369419bafSAndrew Jeffery        @return: Session object
458469419bafSAndrew Jeffery    """
458569419bafSAndrew Jeffery    url = "https://" + host + "/xyz/openbmc_project/control/thermal/enumerate"
458669419bafSAndrew Jeffery
458769419bafSAndrew Jeffery    try:
458869419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
458969419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
459069419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
459169419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
459269419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
459369419bafSAndrew Jeffery    except(requests.exceptions.RequestException) as err:
459469419bafSAndrew Jeffery        return connectionErrHandler(args.json, "RequestException", err)
459569419bafSAndrew Jeffery
459669419bafSAndrew Jeffery    if (res.status_code == 404):
459769419bafSAndrew Jeffery        return "No thermal control zones found"
459869419bafSAndrew Jeffery
459969419bafSAndrew Jeffery    zonesDict = json.loads(res.text)
460069419bafSAndrew Jeffery    if not zonesDict['data']:
460169419bafSAndrew Jeffery        return "No thermal control zones found"
460269419bafSAndrew Jeffery    for zone in zonesDict['data']:
460369419bafSAndrew Jeffery        z = ",".join(str(zone.split('/')[-1]) for zone in zonesDict['data'])
460469419bafSAndrew Jeffery
460569419bafSAndrew Jeffery    return "Zones: [ " + z + " ]"
460669419bafSAndrew Jeffery
460769419bafSAndrew Jeffery
460869419bafSAndrew Jefferydef getThermalMode(host, args, session):
460969419bafSAndrew Jeffery    """
461069419bafSAndrew Jeffery        Get thermal control mode
461169419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
461269419bafSAndrew Jeffery        @param args: contains additional arguments used to get the thermal
461369419bafSAndrew Jeffery               control mode
461469419bafSAndrew Jeffery        @param session: the active session to use
461569419bafSAndrew Jeffery        @param args.zone: the zone to get the mode on
461669419bafSAndrew Jeffery        @return: Session object
461769419bafSAndrew Jeffery    """
461869419bafSAndrew Jeffery    url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
461969419bafSAndrew Jeffery        args.zone
462069419bafSAndrew Jeffery
462169419bafSAndrew Jeffery    try:
462269419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
462369419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
462469419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
462569419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
462669419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
462769419bafSAndrew Jeffery    except(requests.exceptions.RequestException) as err:
462869419bafSAndrew Jeffery        return connectionErrHandler(args.json, "RequestException", err)
462969419bafSAndrew Jeffery
463069419bafSAndrew Jeffery    if (res.status_code == 404):
463169419bafSAndrew Jeffery        return "Thermal control zone(" + args.zone + ") not found"
463269419bafSAndrew Jeffery
463369419bafSAndrew Jeffery    propsDict = json.loads(res.text)
463469419bafSAndrew Jeffery    if not propsDict['data']:
463569419bafSAndrew Jeffery        return "No thermal control properties found on zone(" + args.zone + ")"
463669419bafSAndrew Jeffery    curMode = "Current"
463769419bafSAndrew Jeffery    supModes = "Supported"
463869419bafSAndrew Jeffery    result = "\n"
463969419bafSAndrew Jeffery    for prop in propsDict['data']:
464069419bafSAndrew Jeffery        if (prop.casefold() == curMode.casefold()):
464169419bafSAndrew Jeffery            result += curMode + " Mode: " + propsDict['data'][curMode] + "\n"
464269419bafSAndrew Jeffery        if (prop.casefold() == supModes.casefold()):
464369419bafSAndrew Jeffery            s = ", ".join(str(sup) for sup in propsDict['data'][supModes])
464469419bafSAndrew Jeffery            result += supModes + " Modes: [ " + s + " ]\n"
464569419bafSAndrew Jeffery
464669419bafSAndrew Jeffery    return result
464769419bafSAndrew Jeffery
464869419bafSAndrew Jefferydef setThermalMode(host, args, session):
464969419bafSAndrew Jeffery    """
465069419bafSAndrew Jeffery        Set thermal control mode
465169419bafSAndrew Jeffery        @param host: string, the hostname or IP address of the bmc
465269419bafSAndrew Jeffery        @param args: contains additional arguments used for setting the thermal
465369419bafSAndrew Jeffery               control mode
465469419bafSAndrew Jeffery        @param session: the active session to use
465569419bafSAndrew Jeffery        @param args.zone: the zone to set the mode on
465669419bafSAndrew Jeffery        @param args.mode: the mode to enable
465769419bafSAndrew Jeffery        @return: Session object
465869419bafSAndrew Jeffery    """
465969419bafSAndrew Jeffery    url = "https://" + host + "/xyz/openbmc_project/control/thermal/" + \
466069419bafSAndrew Jeffery        args.zone + "/attr/Current"
466169419bafSAndrew Jeffery
466269419bafSAndrew Jeffery    # Check args.mode against supported modes using `getThermalMode` output
466369419bafSAndrew Jeffery    modes = getThermalMode(host, args, session)
466469419bafSAndrew Jeffery    modes = os.linesep.join([m for m in modes.splitlines() if m])
466569419bafSAndrew Jeffery    modes = modes.replace("\n", ";").strip()
466669419bafSAndrew Jeffery    modesDict = dict(m.split(': ') for m in modes.split(';'))
466769419bafSAndrew Jeffery    sModes = ''.join(s for s in modesDict['Supported Modes'] if s not in '[ ]')
466869419bafSAndrew Jeffery    if args.mode.casefold() not in \
466969419bafSAndrew Jeffery            (m.casefold() for m in sModes.split(',')) or not args.mode:
467069419bafSAndrew Jeffery        result = ("Unsupported mode('" + args.mode + "') given, " +
467169419bafSAndrew Jeffery                  "select a supported mode: \n" +
467269419bafSAndrew Jeffery                  getThermalMode(host, args, session))
467369419bafSAndrew Jeffery        return result
467469419bafSAndrew Jeffery
467569419bafSAndrew Jeffery    data = '{"data":"' + args.mode + '"}'
467669419bafSAndrew Jeffery    try:
467769419bafSAndrew Jeffery        res = session.get(url, headers=jsonHeader, verify=False, timeout=30)
467869419bafSAndrew Jeffery    except(requests.exceptions.Timeout):
467969419bafSAndrew Jeffery        return(connectionErrHandler(args.json, "Timeout", None))
468069419bafSAndrew Jeffery    except(requests.exceptions.ConnectionError) as err:
468169419bafSAndrew Jeffery        return connectionErrHandler(args.json, "ConnectionError", err)
468269419bafSAndrew Jeffery    except(requests.exceptions.RequestException) as err:
468369419bafSAndrew Jeffery        return connectionErrHandler(args.json, "RequestException", err)
468469419bafSAndrew Jeffery
468569419bafSAndrew Jeffery    if (data and res.status_code != 404):
468669419bafSAndrew Jeffery        try:
468769419bafSAndrew Jeffery            res = session.put(url, headers=jsonHeader,
468869419bafSAndrew Jeffery                              data=data, verify=False,
468969419bafSAndrew Jeffery                              timeout=30)
469069419bafSAndrew Jeffery        except(requests.exceptions.Timeout):
469169419bafSAndrew Jeffery            return(connectionErrHandler(args.json, "Timeout", None))
469269419bafSAndrew Jeffery        except(requests.exceptions.ConnectionError) as err:
469369419bafSAndrew Jeffery            return connectionErrHandler(args.json, "ConnectionError", err)
469469419bafSAndrew Jeffery        except(requests.exceptions.RequestException) as err:
469569419bafSAndrew Jeffery            return connectionErrHandler(args.json, "RequestException", err)
469669419bafSAndrew Jeffery
469769419bafSAndrew Jeffery        if res.status_code == 403:
469869419bafSAndrew Jeffery            return "The specified thermal control zone(" + args.zone + ")" + \
469969419bafSAndrew Jeffery                " does not exist"
470069419bafSAndrew Jeffery
470169419bafSAndrew Jeffery        return res.text
470269419bafSAndrew Jeffery    else:
470369419bafSAndrew Jeffery        return "Setting thermal control mode(" + args.mode + ")" + \
470469419bafSAndrew Jeffery            " not supported or operation not available"
470569419bafSAndrew Jeffery
470669419bafSAndrew Jeffery
470769419bafSAndrew Jefferydef createCommandParser():
470869419bafSAndrew Jeffery    """
470969419bafSAndrew Jeffery         creates the parser for the command line along with help for each command and subcommand
471069419bafSAndrew Jeffery
471169419bafSAndrew Jeffery         @return: returns the parser for the command line
471269419bafSAndrew Jeffery    """
471369419bafSAndrew Jeffery    parser = argparse.ArgumentParser(description='Process arguments')
471469419bafSAndrew Jeffery    parser.add_argument("-H", "--host", help='A hostname or IP for the BMC')
471569419bafSAndrew Jeffery    parser.add_argument("-U", "--user", help='The username to login with')
471669419bafSAndrew Jeffery    group = parser.add_mutually_exclusive_group()
471769419bafSAndrew Jeffery    group.add_argument("-A", "--askpw", action='store_true', help='prompt for password')
471869419bafSAndrew Jeffery    group.add_argument("-P", "--PW", help='Provide the password in-line')
471969419bafSAndrew Jeffery    group.add_argument("-E", "--PWenvvar", action='store_true', help='Get password from envvar OPENBMCTOOL_PASSWORD')
472069419bafSAndrew Jeffery    parser.add_argument('-j', '--json', action='store_true', help='output json data only')
472169419bafSAndrew Jeffery    parser.add_argument('-t', '--policyTableLoc', help='The location of the policy table to parse alerts')
472269419bafSAndrew Jeffery    parser.add_argument('-c', '--CerFormat', action='store_true', help=argparse.SUPPRESS)
472369419bafSAndrew Jeffery    parser.add_argument('-T', '--procTime', action='store_true', help= argparse.SUPPRESS)
472469419bafSAndrew Jeffery    parser.add_argument('-V', '--version', action='store_true', help='Display the version number of the openbmctool')
472569419bafSAndrew Jeffery    subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
472669419bafSAndrew Jeffery
472769419bafSAndrew Jeffery    #fru command
472869419bafSAndrew Jeffery    parser_inv = subparsers.add_parser("fru", help='Work with platform inventory')
472969419bafSAndrew Jeffery    inv_subparser = parser_inv.add_subparsers(title='subcommands', description='valid inventory actions', help="valid inventory actions", dest='command')
473069419bafSAndrew Jeffery    inv_subparser.required = True
473169419bafSAndrew Jeffery    #fru print
473269419bafSAndrew Jeffery    inv_print = inv_subparser.add_parser("print", help="prints out a list of all FRUs")
473369419bafSAndrew Jeffery    inv_print.set_defaults(func=fruPrint)
473469419bafSAndrew Jeffery    #fru list [0....n]
473569419bafSAndrew Jeffery    inv_list = inv_subparser.add_parser("list", help="print out details on selected FRUs. Specifying no items will list the entire inventory")
473669419bafSAndrew Jeffery    inv_list.add_argument('items', nargs='?', help="print out details on selected FRUs. Specifying no items will list the entire inventory")
473769419bafSAndrew Jeffery    inv_list.set_defaults(func=fruList)
473869419bafSAndrew Jeffery    #fru status
473969419bafSAndrew Jeffery    inv_status = inv_subparser.add_parser("status", help="prints out the status of all FRUs")
474069419bafSAndrew Jeffery    inv_status.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
474169419bafSAndrew Jeffery    inv_status.set_defaults(func=fruStatus)
474269419bafSAndrew Jeffery
474369419bafSAndrew Jeffery    #sensors command
474469419bafSAndrew Jeffery    parser_sens = subparsers.add_parser("sensors", help="Work with platform sensors")
474569419bafSAndrew Jeffery    sens_subparser=parser_sens.add_subparsers(title='subcommands', description='valid sensor actions', help='valid sensor actions', dest='command')
474669419bafSAndrew Jeffery    sens_subparser.required = True
474769419bafSAndrew Jeffery    #sensor print
474869419bafSAndrew Jeffery    sens_print= sens_subparser.add_parser('print', help="prints out a list of all Sensors.")
474969419bafSAndrew Jeffery    sens_print.set_defaults(func=sensor)
475069419bafSAndrew Jeffery    #sensor list[0...n]
475169419bafSAndrew Jeffery    sens_list=sens_subparser.add_parser("list", help="Lists all Sensors in the platform. Specify a sensor for full details. ")
475269419bafSAndrew Jeffery    sens_list.add_argument("sensNum", nargs='?', help="The Sensor number to get full details on" )
475369419bafSAndrew Jeffery    sens_list.set_defaults(func=sensor)
475469419bafSAndrew Jeffery
475569419bafSAndrew Jeffery    #thermal control commands
475669419bafSAndrew Jeffery    parser_therm = subparsers.add_parser("thermal", help="Work with thermal control parameters")
475769419bafSAndrew Jeffery    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')
475869419bafSAndrew Jeffery    #thermal control zones
475969419bafSAndrew Jeffery    parser_thermZones = therm_subparser.add_parser("zones", help="Get a list of available thermal control zones")
476069419bafSAndrew Jeffery    parser_thermZones.set_defaults(func=getThermalZones)
476169419bafSAndrew Jeffery    #thermal control modes
476269419bafSAndrew Jeffery    parser_thermMode = therm_subparser.add_parser("modes", help="Work with thermal control modes")
476369419bafSAndrew Jeffery    thermMode_sub = parser_thermMode.add_subparsers(title='subactions', description='Work with thermal control modes', help="Work with thermal control modes")
476469419bafSAndrew Jeffery    #get thermal control mode
476569419bafSAndrew Jeffery    parser_getThermMode = thermMode_sub.add_parser("get", help="Get current and supported thermal control modes")
476669419bafSAndrew Jeffery    parser_getThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
476769419bafSAndrew Jeffery    parser_getThermMode.set_defaults(func=getThermalMode)
476869419bafSAndrew Jeffery    #set thermal control mode
476969419bafSAndrew Jeffery    parser_setThermMode = thermMode_sub.add_parser("set", help="Set the thermal control mode")
477069419bafSAndrew Jeffery    parser_setThermMode.add_argument('-z', '--zone', required=True, help='Thermal zone to work with')
477169419bafSAndrew Jeffery    parser_setThermMode.add_argument('-m', '--mode', required=True, help='The supported thermal control mode')
477269419bafSAndrew Jeffery    parser_setThermMode.set_defaults(func=setThermalMode)
477369419bafSAndrew Jeffery
477469419bafSAndrew Jeffery    #sel command
477569419bafSAndrew Jeffery    parser_sel = subparsers.add_parser("sel", help="Work with platform alerts")
477669419bafSAndrew Jeffery    sel_subparser = parser_sel.add_subparsers(title='subcommands', description='valid SEL actions', help = 'valid SEL actions', dest='command')
477769419bafSAndrew Jeffery    sel_subparser.required = True
477869419bafSAndrew Jeffery    #sel print
477969419bafSAndrew Jeffery    sel_print = sel_subparser.add_parser("print", help="prints out a list of all sels in a condensed list")
478069419bafSAndrew Jeffery    sel_print.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
478169419bafSAndrew Jeffery    sel_print.add_argument('-v', '--verbose', action='store_true', help="Changes the output to being very verbose")
478269419bafSAndrew Jeffery    sel_print.add_argument('-f', '--fileloc', help='Parse a file instead of the BMC output')
478369419bafSAndrew Jeffery    sel_print.set_defaults(func=selPrint)
478469419bafSAndrew Jeffery
478569419bafSAndrew Jeffery    #sel list
478669419bafSAndrew Jeffery    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")
478769419bafSAndrew Jeffery    sel_list.add_argument("selNum", nargs='?', type=int, help="The SEL entry to get details on")
478869419bafSAndrew Jeffery    sel_list.set_defaults(func=selList)
478969419bafSAndrew Jeffery
479069419bafSAndrew Jeffery    sel_get = sel_subparser.add_parser("get", help="Gets the verbose details of a specified SEL entry")
479169419bafSAndrew Jeffery    sel_get.add_argument('selNum', type=int, help="the number of the SEL entry to get")
479269419bafSAndrew Jeffery    sel_get.set_defaults(func=selList)
479369419bafSAndrew Jeffery
479469419bafSAndrew Jeffery    sel_clear = sel_subparser.add_parser("clear", help="Clears all entries from the SEL")
479569419bafSAndrew Jeffery    sel_clear.set_defaults(func=selClear)
479669419bafSAndrew Jeffery
479769419bafSAndrew Jeffery    sel_setResolved = sel_subparser.add_parser("resolve", help="Sets the sel entry to resolved")
479869419bafSAndrew Jeffery    sel_setResolved.add_argument('-n', '--selNum', type=int, help="the number of the SEL entry to resolve")
479969419bafSAndrew Jeffery    sel_ResolveAll_sub = sel_setResolved.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
480069419bafSAndrew Jeffery    sel_ResolveAll = sel_ResolveAll_sub.add_parser('all', help='Resolve all SEL entries')
480169419bafSAndrew Jeffery    sel_ResolveAll.set_defaults(func=selResolveAll)
480269419bafSAndrew Jeffery    sel_setResolved.set_defaults(func=selSetResolved)
480369419bafSAndrew Jeffery
480469419bafSAndrew Jeffery    parser_chassis = subparsers.add_parser("chassis", help="Work with chassis power and status")
480569419bafSAndrew Jeffery    chas_sub = parser_chassis.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
480669419bafSAndrew Jeffery
480769419bafSAndrew Jeffery    parser_chassis.add_argument('status', action='store_true', help='Returns the current status of the platform')
480869419bafSAndrew Jeffery    parser_chassis.set_defaults(func=chassis)
480969419bafSAndrew Jeffery
481069419bafSAndrew Jeffery    parser_chasPower = chas_sub.add_parser("power", help="Turn the chassis on or off, check the power state")
481169419bafSAndrew Jeffery    parser_chasPower.add_argument('powcmd',  choices=['on','softoff', 'hardoff', 'status'], help='The value for the power command. on, off, or status')
481269419bafSAndrew Jeffery    parser_chasPower.set_defaults(func=chassisPower)
481369419bafSAndrew Jeffery
481469419bafSAndrew Jeffery    #control the chassis identify led
481569419bafSAndrew Jeffery    parser_chasIdent = chas_sub.add_parser("identify", help="Control the chassis identify led")
481669419bafSAndrew Jeffery    parser_chasIdent.add_argument('identcmd', choices=['on', 'off', 'status'], help='The control option for the led: on, off, blink, status')
481769419bafSAndrew Jeffery    parser_chasIdent.set_defaults(func=chassisIdent)
481869419bafSAndrew Jeffery
481969419bafSAndrew Jeffery    #collect service data
482069419bafSAndrew Jeffery    parser_servData = subparsers.add_parser("collect_service_data", help="Collect all bmc data needed for service")
482169419bafSAndrew Jeffery    parser_servData.add_argument('-d', '--devdebug', action='store_true', help=argparse.SUPPRESS)
482269419bafSAndrew Jeffery    parser_servData.set_defaults(func=collectServiceData)
482369419bafSAndrew Jeffery
482469419bafSAndrew Jeffery    #system quick health check
482569419bafSAndrew Jeffery    parser_healthChk = subparsers.add_parser("health_check", help="Work with platform sensors")
482669419bafSAndrew Jeffery    parser_healthChk.set_defaults(func=healthCheck)
482769419bafSAndrew Jeffery
48284e178110SAsmitha Karunanithi    #tasks
48294e178110SAsmitha Karunanithi    parser_tasks = subparsers.add_parser("task", help="Work with tasks")
48304e178110SAsmitha Karunanithi    tasks_sub = parser_tasks.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
48314e178110SAsmitha Karunanithi    tasks_sub.required = True
48324e178110SAsmitha Karunanithi    get_Task = tasks_sub.add_parser('get', help="Get on Task Monitor URL")
48334e178110SAsmitha Karunanithi    get_Task.add_argument("-u", "--taskURI", help="Task Monitor URI")
48344e178110SAsmitha Karunanithi    get_Task.set_defaults(func=getTask)
48354e178110SAsmitha Karunanithi
483669419bafSAndrew Jeffery    #work with dumps
483769419bafSAndrew Jeffery    parser_bmcdump = subparsers.add_parser("dump", help="Work with dumps")
483869419bafSAndrew Jeffery    parser_bmcdump.add_argument("-t", "--dumpType", default='bmc', choices=['bmc','SystemDump'],help="Type of dump")
483969419bafSAndrew Jeffery    bmcDump_sub = parser_bmcdump.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
484069419bafSAndrew Jeffery    bmcDump_sub.required = True
484169419bafSAndrew Jeffery    dump_Create = bmcDump_sub.add_parser('create', help="Create a dump of given type")
484269419bafSAndrew Jeffery    dump_Create.set_defaults(func=dumpCreate)
484369419bafSAndrew Jeffery
484469419bafSAndrew Jeffery    dump_list = bmcDump_sub.add_parser('list', help="list all dumps")
484569419bafSAndrew Jeffery    dump_list.set_defaults(func=dumpList)
484669419bafSAndrew Jeffery
484769419bafSAndrew Jeffery    parserdumpdelete = bmcDump_sub.add_parser('delete', help="Delete dump")
484869419bafSAndrew Jeffery    parserdumpdelete.add_argument("-n", "--dumpNum", nargs='*', type=int, help="The Dump entry to delete")
484969419bafSAndrew Jeffery    parserdumpdelete.set_defaults(func=dumpDelete)
485069419bafSAndrew Jeffery
485169419bafSAndrew Jeffery    bmcDumpDelsub = parserdumpdelete.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
485269419bafSAndrew Jeffery    deleteAllDumps = bmcDumpDelsub.add_parser('all', help='Delete all dumps')
485369419bafSAndrew Jeffery    deleteAllDumps.set_defaults(func=dumpDeleteAll)
485469419bafSAndrew Jeffery
485569419bafSAndrew Jeffery    parser_dumpretrieve = bmcDump_sub.add_parser('retrieve', help='Retrieve a dump file')
485669419bafSAndrew Jeffery    parser_dumpretrieve.add_argument("-n,", "--dumpNum", help="The Dump entry to retrieve")
485769419bafSAndrew Jeffery    parser_dumpretrieve.add_argument("-s", "--dumpSaveLoc", help="The location to save the bmc dump file or file path for system dump")
485869419bafSAndrew Jeffery    parser_dumpretrieve.set_defaults(func=dumpRetrieve)
485969419bafSAndrew Jeffery
486069419bafSAndrew Jeffery    #bmc command for reseting the bmc
486169419bafSAndrew Jeffery    parser_bmc = subparsers.add_parser('bmc', help="Work with the bmc")
486269419bafSAndrew Jeffery    bmc_sub = parser_bmc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
486369419bafSAndrew Jeffery    parser_BMCReset = bmc_sub.add_parser('reset', help='Reset the bmc' )
486469419bafSAndrew Jeffery    parser_BMCReset.add_argument('type', choices=['warm','cold'], help="Warm: Reboot the BMC, Cold: CLEAR config and reboot bmc")
486569419bafSAndrew Jeffery    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.")
486669419bafSAndrew Jeffery    parser_bmc.set_defaults(func=bmc)
486769419bafSAndrew Jeffery
486869419bafSAndrew Jeffery    #add alias to the bmc command
486969419bafSAndrew Jeffery    parser_mc = subparsers.add_parser('mc', help="Work with the management controller")
487069419bafSAndrew Jeffery    mc_sub = parser_mc.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
487169419bafSAndrew Jeffery    parser_MCReset = mc_sub.add_parser('reset', help='Reset the bmc' )
487269419bafSAndrew Jeffery    parser_MCReset.add_argument('type', choices=['warm','cold'], help="Reboot the BMC")
487369419bafSAndrew Jeffery    #parser_MCReset.add_argument('cold', action='store_true', help="Reboot the BMC and CLEAR the configuration")
487469419bafSAndrew Jeffery    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.")
487569419bafSAndrew Jeffery    parser_MCReset.set_defaults(func=bmcReset)
487669419bafSAndrew Jeffery    parser_mc.set_defaults(func=bmc)
487769419bafSAndrew Jeffery
487869419bafSAndrew Jeffery    #gard clear
487969419bafSAndrew Jeffery    parser_gc = subparsers.add_parser("gardclear", help="Used to clear gard records")
488069419bafSAndrew Jeffery    parser_gc.set_defaults(func=gardClear)
488169419bafSAndrew Jeffery
488269419bafSAndrew Jeffery    #firmware_flash
488369419bafSAndrew Jeffery    parser_fw = subparsers.add_parser("firmware", help="Work with the system firmware")
488469419bafSAndrew Jeffery    fwflash_subproc = parser_fw.add_subparsers(title='subcommands', description='valid firmware commands', help='sub-command help', dest='command')
488569419bafSAndrew Jeffery    fwflash_subproc.required = True
488669419bafSAndrew Jeffery
488769419bafSAndrew Jeffery    fwflash = fwflash_subproc.add_parser('flash', help="Flash the system firmware")
488869419bafSAndrew Jeffery    fwflash.add_argument('type', choices=['bmc', 'pnor'], help="image type to flash")
488969419bafSAndrew Jeffery    fwflash.add_argument('-f', '--fileloc', required=True, help="The absolute path to the firmware image")
489069419bafSAndrew Jeffery    fwflash.set_defaults(func=fwFlash)
489169419bafSAndrew Jeffery
489269419bafSAndrew Jeffery    fwActivate = fwflash_subproc.add_parser('activate', help="Activate existing image on the bmc")
489369419bafSAndrew Jeffery    fwActivate.add_argument('imageID', help="The image ID to activate from the firmware list. Ex: 63c95399")
489469419bafSAndrew Jeffery    fwActivate.set_defaults(func=activateFWImage)
489569419bafSAndrew Jeffery
489669419bafSAndrew Jeffery    fwActivateStatus = fwflash_subproc.add_parser('activation_status', help="Check Status of activations")
489769419bafSAndrew Jeffery    fwActivateStatus.set_defaults(func=activateStatus)
489869419bafSAndrew Jeffery
489969419bafSAndrew Jeffery    fwList = fwflash_subproc.add_parser('list', help="List all of the installed firmware")
490069419bafSAndrew Jeffery    fwList.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
490169419bafSAndrew Jeffery    fwList.set_defaults(func=firmwareList)
490269419bafSAndrew Jeffery
490369419bafSAndrew Jeffery    fwprint = fwflash_subproc.add_parser('print', help="List all of the installed firmware")
490469419bafSAndrew Jeffery    fwprint.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
490569419bafSAndrew Jeffery    fwprint.set_defaults(func=firmwareList)
490669419bafSAndrew Jeffery
490769419bafSAndrew Jeffery    fwDelete = fwflash_subproc.add_parser('delete', help="Delete an existing firmware version")
490869419bafSAndrew Jeffery    fwDelete.add_argument('versionID', help="The version ID to delete from the firmware list. Ex: 63c95399")
490969419bafSAndrew Jeffery    fwDelete.set_defaults(func=deleteFWVersion)
491069419bafSAndrew Jeffery
4911*0b5b2041SKlaus Heinrich Kiwi    fwDeleteAll = fwflash_subproc.add_parser('deleteAll', help="Delete ALL firmware versions")
4912*0b5b2041SKlaus Heinrich Kiwi    fwDeleteAll.set_defaults(func=deleteFWAll)
4913*0b5b2041SKlaus Heinrich Kiwi
491469419bafSAndrew Jeffery    #logging
491569419bafSAndrew Jeffery    parser_logging = subparsers.add_parser("logging", help="logging controls")
491669419bafSAndrew Jeffery    logging_sub = parser_logging.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
491769419bafSAndrew Jeffery
491869419bafSAndrew Jeffery    #turn rest api logging on/off
491969419bafSAndrew Jeffery    parser_rest_logging = logging_sub.add_parser("rest_api", help="turn rest api logging on/off")
492069419bafSAndrew Jeffery    parser_rest_logging.add_argument('rest_logging', choices=['on', 'off'], help='The control option for rest logging: on, off')
492169419bafSAndrew Jeffery    parser_rest_logging.set_defaults(func=restLogging)
492269419bafSAndrew Jeffery
492369419bafSAndrew Jeffery    #remote logging
492469419bafSAndrew Jeffery    parser_remote_logging = logging_sub.add_parser("remote_logging", help="Remote logging (rsyslog) commands")
492569419bafSAndrew Jeffery    parser_remote_logging.add_argument('remote_logging', choices=['view', 'disable'], help='Remote logging (rsyslog) commands')
492669419bafSAndrew Jeffery    parser_remote_logging.set_defaults(func=remoteLogging)
492769419bafSAndrew Jeffery
492869419bafSAndrew Jeffery    #configure remote logging
492969419bafSAndrew Jeffery    parser_remote_logging_config = logging_sub.add_parser("remote_logging_config", help="Configure remote logging (rsyslog)")
493069419bafSAndrew Jeffery    parser_remote_logging_config.add_argument("-a", "--address", required=True, help="Set IP address of rsyslog server")
493169419bafSAndrew Jeffery    parser_remote_logging_config.add_argument("-p", "--port", required=True, type=int, help="Set Port of rsyslog server")
493269419bafSAndrew Jeffery    parser_remote_logging_config.set_defaults(func=remoteLoggingConfig)
493369419bafSAndrew Jeffery
493469419bafSAndrew Jeffery    #certificate management
493569419bafSAndrew Jeffery    parser_cert = subparsers.add_parser("certificate", help="Certificate management")
493669419bafSAndrew Jeffery    certMgmt_subproc = parser_cert.add_subparsers(title='subcommands', description='valid certificate commands', help='sub-command help', dest='command')
493769419bafSAndrew Jeffery
493869419bafSAndrew Jeffery    certUpdate = certMgmt_subproc.add_parser('update', help="Update the certificate")
493969419bafSAndrew Jeffery    certUpdate.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to update")
494069419bafSAndrew Jeffery    certUpdate.add_argument('service', choices=['https', 'ldap'], help="Service to update")
494169419bafSAndrew Jeffery    certUpdate.add_argument('-f', '--fileloc', required=True, help="The absolute path to the certificate file")
494269419bafSAndrew Jeffery    certUpdate.set_defaults(func=certificateUpdate)
494369419bafSAndrew Jeffery
494469419bafSAndrew Jeffery    certDelete = certMgmt_subproc.add_parser('delete', help="Delete the certificate")
494569419bafSAndrew Jeffery    certDelete.add_argument('type', choices=['server', 'client', 'authority'], help="certificate type to delete")
494669419bafSAndrew Jeffery    certDelete.add_argument('service', choices=['https', 'ldap'], help="Service to delete the certificate")
494769419bafSAndrew Jeffery    certDelete.set_defaults(func=certificateDelete)
494869419bafSAndrew Jeffery
494969419bafSAndrew Jeffery    certReplace = certMgmt_subproc.add_parser('replace',
495069419bafSAndrew Jeffery        help="Replace the certificate")
495169419bafSAndrew Jeffery    certReplace.add_argument('type', choices=['server', 'client', 'authority'],
495269419bafSAndrew Jeffery        help="certificate type to replace")
495369419bafSAndrew Jeffery    certReplace.add_argument('service', choices=['https', 'ldap'],
495469419bafSAndrew Jeffery        help="Service to replace the certificate")
495569419bafSAndrew Jeffery    certReplace.add_argument('-f', '--fileloc', required=True,
495669419bafSAndrew Jeffery        help="The absolute path to the certificate file")
495769419bafSAndrew Jeffery    certReplace.set_defaults(func=certificateReplace)
495869419bafSAndrew Jeffery
495969419bafSAndrew Jeffery    certDisplay = certMgmt_subproc.add_parser('display',
496069419bafSAndrew Jeffery        help="Print the certificate")
496169419bafSAndrew Jeffery    certDisplay.add_argument('type', choices=['server', 'client', 'authority'],
496269419bafSAndrew Jeffery        help="certificate type to display")
496369419bafSAndrew Jeffery    certDisplay.set_defaults(func=certificateDisplay)
496469419bafSAndrew Jeffery
496569419bafSAndrew Jeffery    certList = certMgmt_subproc.add_parser('list',
496669419bafSAndrew Jeffery        help="Certificate list")
496769419bafSAndrew Jeffery    certList.set_defaults(func=certificateList)
496869419bafSAndrew Jeffery
496969419bafSAndrew Jeffery    certGenerateCSR = certMgmt_subproc.add_parser('generatecsr', help="Generate CSR")
497069419bafSAndrew Jeffery    certGenerateCSR.add_argument('type', choices=['server', 'client', 'authority'],
497169419bafSAndrew Jeffery        help="Generate CSR")
497269419bafSAndrew Jeffery    certGenerateCSR.add_argument('city',
497369419bafSAndrew Jeffery        help="The city or locality of the organization making the request")
497469419bafSAndrew Jeffery    certGenerateCSR.add_argument('commonName',
497569419bafSAndrew Jeffery        help="The fully qualified domain name of the component that is being secured.")
497669419bafSAndrew Jeffery    certGenerateCSR.add_argument('country',
497769419bafSAndrew Jeffery        help="The country of the organization making the request")
497869419bafSAndrew Jeffery    certGenerateCSR.add_argument('organization',
497969419bafSAndrew Jeffery        help="The name of the organization making the request.")
498069419bafSAndrew Jeffery    certGenerateCSR.add_argument('organizationUnit',
498169419bafSAndrew Jeffery        help="The name of the unit or division of the organization making the request.")
498269419bafSAndrew Jeffery    certGenerateCSR.add_argument('state',
498369419bafSAndrew Jeffery        help="The state, province, or region of the organization making the request.")
498469419bafSAndrew Jeffery    certGenerateCSR.add_argument('keyPairAlgorithm',  choices=['RSA', 'EC'],
498569419bafSAndrew Jeffery        help="The type of key pair for use with signing algorithms.")
498669419bafSAndrew Jeffery    certGenerateCSR.add_argument('keyCurveId',
498769419bafSAndrew Jeffery        help="The curve ID to be used with the key, if needed based on the value of the 'KeyPairAlgorithm' parameter.")
498869419bafSAndrew Jeffery    certGenerateCSR.add_argument('contactPerson',
498969419bafSAndrew Jeffery        help="The name of the user making the request")
499069419bafSAndrew Jeffery    certGenerateCSR.add_argument('email',
499169419bafSAndrew Jeffery        help="The email address of the contact within the organization")
499269419bafSAndrew Jeffery    certGenerateCSR.add_argument('alternativeNames',
499369419bafSAndrew Jeffery        help="Additional hostnames of the component that is being secured")
499469419bafSAndrew Jeffery    certGenerateCSR.add_argument('givenname',
499569419bafSAndrew Jeffery        help="The given name of the user making the request")
499669419bafSAndrew Jeffery    certGenerateCSR.add_argument('surname',
499769419bafSAndrew Jeffery        help="The surname of the user making the request")
499869419bafSAndrew Jeffery    certGenerateCSR.add_argument('unstructuredname',
499969419bafSAndrew Jeffery        help="he unstructured name of the subject")
500069419bafSAndrew Jeffery    certGenerateCSR.add_argument('initials',
500169419bafSAndrew Jeffery        help="The initials of the user making the request")
500269419bafSAndrew Jeffery    certGenerateCSR.set_defaults(func=certificateGenerateCSR)
500369419bafSAndrew Jeffery
500469419bafSAndrew Jeffery    # local users
500569419bafSAndrew Jeffery    parser_users = subparsers.add_parser("local_users", help="Work with local users")
500669419bafSAndrew Jeffery    parser_users.add_argument('local_users', choices=['disableall','enableall', 'queryenabled'], help="Disable, enable or query local user accounts")
500769419bafSAndrew Jeffery    parser_users.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
500869419bafSAndrew Jeffery    parser_users.set_defaults(func=localUsers)
500969419bafSAndrew Jeffery
501069419bafSAndrew Jeffery    #LDAP
501169419bafSAndrew Jeffery    parser_ldap = subparsers.add_parser("ldap", help="LDAP controls")
501269419bafSAndrew Jeffery    ldap_sub = parser_ldap.add_subparsers(title='subcommands', description='valid subcommands',help="sub-command help", dest='command')
501369419bafSAndrew Jeffery
501469419bafSAndrew Jeffery    #configure and enable LDAP
501569419bafSAndrew Jeffery    parser_ldap_config = ldap_sub.add_parser("enable", help="Configure and enables the LDAP")
501669419bafSAndrew Jeffery    parser_ldap_config.add_argument("-a", "--uri", required=True, help="Set LDAP server URI")
501769419bafSAndrew Jeffery    parser_ldap_config.add_argument("-B", "--bindDN", required=True, help="Set the bind DN of the LDAP server")
501869419bafSAndrew Jeffery    parser_ldap_config.add_argument("-b", "--baseDN", required=True, help="Set the base DN of the LDAP server")
501969419bafSAndrew Jeffery    parser_ldap_config.add_argument("-p", "--bindPassword", required=True, help="Set the bind password of the LDAP server")
502069419bafSAndrew Jeffery    parser_ldap_config.add_argument("-S", "--scope", choices=['sub','one', 'base'],
502169419bafSAndrew Jeffery            help='Specifies the search scope:subtree, one level or base object.')
502269419bafSAndrew Jeffery    parser_ldap_config.add_argument("-t", "--serverType", required=True, choices=['ActiveDirectory','OpenLDAP'],
502369419bafSAndrew Jeffery            help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
502469419bafSAndrew Jeffery    parser_ldap_config.add_argument("-g","--groupAttrName", required=False, default='', help="Group Attribute Name")
502569419bafSAndrew Jeffery    parser_ldap_config.add_argument("-u","--userAttrName", required=False, default='', help="User Attribute Name")
502669419bafSAndrew Jeffery    parser_ldap_config.set_defaults(func=enableLDAPConfig)
502769419bafSAndrew Jeffery
502869419bafSAndrew Jeffery    # disable LDAP
502969419bafSAndrew Jeffery    parser_disable_ldap = ldap_sub.add_parser("disable", help="disables the LDAP")
503069419bafSAndrew Jeffery    parser_disable_ldap.set_defaults(func=disableLDAP)
503169419bafSAndrew Jeffery    # view-config
503269419bafSAndrew Jeffery    parser_ldap_config = \
503369419bafSAndrew Jeffery    ldap_sub.add_parser("view-config", help="prints out a list of all \
503469419bafSAndrew Jeffery                        LDAPS's configured properties")
503569419bafSAndrew Jeffery    parser_ldap_config.set_defaults(func=viewLDAPConfig)
503669419bafSAndrew Jeffery
503769419bafSAndrew Jeffery    #create group privilege mapping
503869419bafSAndrew Jeffery    parser_ldap_mapper = ldap_sub.add_parser("privilege-mapper", help="LDAP group privilege controls")
503969419bafSAndrew Jeffery    parser_ldap_mapper_sub = parser_ldap_mapper.add_subparsers(title='subcommands', description='valid subcommands',
504069419bafSAndrew Jeffery            help="sub-command help", dest='command')
504169419bafSAndrew Jeffery
504269419bafSAndrew Jeffery    parser_ldap_mapper_create = parser_ldap_mapper_sub.add_parser("create", help="Create mapping of ldap group and privilege")
504369419bafSAndrew Jeffery    parser_ldap_mapper_create.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
504469419bafSAndrew Jeffery            help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
504569419bafSAndrew Jeffery    parser_ldap_mapper_create.add_argument("-g","--groupName",required=True,help="Group Name")
504669419bafSAndrew Jeffery    parser_ldap_mapper_create.add_argument("-p","--privilege",choices=['priv-admin','priv-operator','priv-user','priv-callback'],required=True,help="Privilege")
504769419bafSAndrew Jeffery    parser_ldap_mapper_create.set_defaults(func=createPrivilegeMapping)
504869419bafSAndrew Jeffery
504969419bafSAndrew Jeffery    #list group privilege mapping
505069419bafSAndrew Jeffery    parser_ldap_mapper_list = parser_ldap_mapper_sub.add_parser("list",help="List privilege mapping")
505169419bafSAndrew Jeffery    parser_ldap_mapper_list.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
505269419bafSAndrew Jeffery            help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
505369419bafSAndrew Jeffery    parser_ldap_mapper_list.set_defaults(func=listPrivilegeMapping)
505469419bafSAndrew Jeffery
505569419bafSAndrew Jeffery    #delete group privilege mapping
505669419bafSAndrew Jeffery    parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("delete",help="Delete privilege mapping")
505769419bafSAndrew Jeffery    parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
505869419bafSAndrew Jeffery            help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
505969419bafSAndrew Jeffery    parser_ldap_mapper_delete.add_argument("-g","--groupName",required=True,help="Group Name")
506069419bafSAndrew Jeffery    parser_ldap_mapper_delete.set_defaults(func=deletePrivilegeMapping)
506169419bafSAndrew Jeffery
506269419bafSAndrew Jeffery    #deleteAll group privilege mapping
506369419bafSAndrew Jeffery    parser_ldap_mapper_delete = parser_ldap_mapper_sub.add_parser("purge",help="Delete All privilege mapping")
506469419bafSAndrew Jeffery    parser_ldap_mapper_delete.add_argument("-t", "--serverType", choices=['ActiveDirectory','OpenLDAP'],
506569419bafSAndrew Jeffery            help='Specifies the configured server is ActiveDirectory(AD) or OpenLdap')
506669419bafSAndrew Jeffery    parser_ldap_mapper_delete.set_defaults(func=deleteAllPrivilegeMapping)
506769419bafSAndrew Jeffery
506869419bafSAndrew Jeffery    # set local user password
506969419bafSAndrew Jeffery    parser_set_password = subparsers.add_parser("set_password",
507069419bafSAndrew Jeffery        help="Set password of local user")
507169419bafSAndrew Jeffery    parser_set_password.add_argument( "-p", "--password", required=True,
507269419bafSAndrew Jeffery        help="Password of local user")
507369419bafSAndrew Jeffery    parser_set_password.set_defaults(func=setPassword)
507469419bafSAndrew Jeffery
507569419bafSAndrew Jeffery    # network
507669419bafSAndrew Jeffery    parser_nw = subparsers.add_parser("network", help="network controls")
507769419bafSAndrew Jeffery    nw_sub = parser_nw.add_subparsers(title='subcommands',
507869419bafSAndrew Jeffery                                      description='valid subcommands',
507969419bafSAndrew Jeffery                                      help="sub-command help",
508069419bafSAndrew Jeffery                                      dest='command')
508169419bafSAndrew Jeffery
508269419bafSAndrew Jeffery    # enable DHCP
508369419bafSAndrew Jeffery    parser_enable_dhcp = nw_sub.add_parser("enableDHCP",
508469419bafSAndrew Jeffery                                           help="enables the DHCP on given "
508569419bafSAndrew Jeffery                                           "Interface")
508669419bafSAndrew Jeffery    parser_enable_dhcp.add_argument("-I", "--Interface", required=True,
508769419bafSAndrew Jeffery                                    help="Name of the ethernet interface(it can"
508869419bafSAndrew Jeffery                                    "be obtained by the "
508969419bafSAndrew Jeffery                                    "command:network view-config)"
509069419bafSAndrew Jeffery                                    "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
509169419bafSAndrew Jeffery    parser_enable_dhcp.set_defaults(func=enableDHCP)
509269419bafSAndrew Jeffery
509369419bafSAndrew Jeffery    # disable DHCP
509469419bafSAndrew Jeffery    parser_disable_dhcp = nw_sub.add_parser("disableDHCP",
509569419bafSAndrew Jeffery                                            help="disables the DHCP on given "
509669419bafSAndrew Jeffery                                            "Interface")
509769419bafSAndrew Jeffery    parser_disable_dhcp.add_argument("-I", "--Interface", required=True,
509869419bafSAndrew Jeffery                                     help="Name of the ethernet interface(it can"
509969419bafSAndrew Jeffery                                     "be obtained by the "
510069419bafSAndrew Jeffery                                     "command:network view-config)"
510169419bafSAndrew Jeffery                                     "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
510269419bafSAndrew Jeffery    parser_disable_dhcp.set_defaults(func=disableDHCP)
510369419bafSAndrew Jeffery
510469419bafSAndrew Jeffery    # get HostName
510569419bafSAndrew Jeffery    parser_gethostname = nw_sub.add_parser("getHostName",
510669419bafSAndrew Jeffery                                           help="prints out HostName")
510769419bafSAndrew Jeffery    parser_gethostname.set_defaults(func=getHostname)
510869419bafSAndrew Jeffery
510969419bafSAndrew Jeffery    # set HostName
511069419bafSAndrew Jeffery    parser_sethostname = nw_sub.add_parser("setHostName", help="sets HostName")
511169419bafSAndrew Jeffery    parser_sethostname.add_argument("-H", "--HostName", required=True,
511269419bafSAndrew Jeffery                                    help="A HostName for the BMC")
511369419bafSAndrew Jeffery    parser_sethostname.set_defaults(func=setHostname)
511469419bafSAndrew Jeffery
511569419bafSAndrew Jeffery    # get domainname
511669419bafSAndrew Jeffery    parser_getdomainname = nw_sub.add_parser("getDomainName",
511769419bafSAndrew Jeffery                                             help="prints out DomainName of "
511869419bafSAndrew Jeffery                                             "given Interface")
511969419bafSAndrew Jeffery    parser_getdomainname.add_argument("-I", "--Interface", required=True,
512069419bafSAndrew Jeffery                                      help="Name of the ethernet interface(it "
512169419bafSAndrew Jeffery                                      "can be obtained by the "
512269419bafSAndrew Jeffery                                      "command:network view-config)"
512369419bafSAndrew Jeffery                                      "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
512469419bafSAndrew Jeffery    parser_getdomainname.set_defaults(func=getDomainName)
512569419bafSAndrew Jeffery
512669419bafSAndrew Jeffery    # set domainname
512769419bafSAndrew Jeffery    parser_setdomainname = nw_sub.add_parser("setDomainName",
512869419bafSAndrew Jeffery                                             help="sets DomainName of given "
512969419bafSAndrew Jeffery                                             "Interface")
513069419bafSAndrew Jeffery    parser_setdomainname.add_argument("-D", "--DomainName", required=True,
513169419bafSAndrew Jeffery                                      help="Ex: DomainName=Domain1,Domain2,...")
513269419bafSAndrew Jeffery    parser_setdomainname.add_argument("-I", "--Interface", required=True,
513369419bafSAndrew Jeffery                                      help="Name of the ethernet interface(it "
513469419bafSAndrew Jeffery                                      "can be obtained by the "
513569419bafSAndrew Jeffery                                      "command:network view-config)"
513669419bafSAndrew Jeffery                                      "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
513769419bafSAndrew Jeffery    parser_setdomainname.set_defaults(func=setDomainName)
513869419bafSAndrew Jeffery
513969419bafSAndrew Jeffery    # get MACAddress
514069419bafSAndrew Jeffery    parser_getmacaddress = nw_sub.add_parser("getMACAddress",
514169419bafSAndrew Jeffery                                             help="prints out MACAddress the "
514269419bafSAndrew Jeffery                                             "given Interface")
514369419bafSAndrew Jeffery    parser_getmacaddress.add_argument("-I", "--Interface", required=True,
514469419bafSAndrew Jeffery                                      help="Name of the ethernet interface(it "
514569419bafSAndrew Jeffery                                      "can be obtained by the "
514669419bafSAndrew Jeffery                                      "command:network view-config)"
514769419bafSAndrew Jeffery                                      "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
514869419bafSAndrew Jeffery    parser_getmacaddress.set_defaults(func=getMACAddress)
514969419bafSAndrew Jeffery
515069419bafSAndrew Jeffery    # set MACAddress
515169419bafSAndrew Jeffery    parser_setmacaddress = nw_sub.add_parser("setMACAddress",
515269419bafSAndrew Jeffery                                             help="sets MACAddress")
515369419bafSAndrew Jeffery    parser_setmacaddress.add_argument("-MA", "--MACAddress", required=True,
515469419bafSAndrew Jeffery                                      help="A MACAddress for the given "
515569419bafSAndrew Jeffery                                      "Interface")
515669419bafSAndrew Jeffery    parser_setmacaddress.add_argument("-I", "--Interface", required=True,
515769419bafSAndrew Jeffery                                    help="Name of the ethernet interface(it can"
515869419bafSAndrew Jeffery                                    "be obtained by the "
515969419bafSAndrew Jeffery                                    "command:network view-config)"
516069419bafSAndrew Jeffery                                    "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
516169419bafSAndrew Jeffery    parser_setmacaddress.set_defaults(func=setMACAddress)
516269419bafSAndrew Jeffery
516369419bafSAndrew Jeffery    # get DefaultGW
516469419bafSAndrew Jeffery    parser_getdefaultgw = nw_sub.add_parser("getDefaultGW",
516569419bafSAndrew Jeffery                                            help="prints out DefaultGateway "
516669419bafSAndrew Jeffery                                            "the BMC")
516769419bafSAndrew Jeffery    parser_getdefaultgw.set_defaults(func=getDefaultGateway)
516869419bafSAndrew Jeffery
516969419bafSAndrew Jeffery    # set DefaultGW
517069419bafSAndrew Jeffery    parser_setdefaultgw = nw_sub.add_parser("setDefaultGW",
517169419bafSAndrew Jeffery                                             help="sets DefaultGW")
517269419bafSAndrew Jeffery    parser_setdefaultgw.add_argument("-GW", "--DefaultGW", required=True,
517369419bafSAndrew Jeffery                                      help="A DefaultGateway for the BMC")
517469419bafSAndrew Jeffery    parser_setdefaultgw.set_defaults(func=setDefaultGateway)
517569419bafSAndrew Jeffery
517669419bafSAndrew Jeffery    # view network Config
517769419bafSAndrew Jeffery    parser_ldap_config = nw_sub.add_parser("view-config", help="prints out a "
517869419bafSAndrew Jeffery                                           "list of all network's configured "
517969419bafSAndrew Jeffery                                           "properties")
518069419bafSAndrew Jeffery    parser_ldap_config.set_defaults(func=viewNWConfig)
518169419bafSAndrew Jeffery
518269419bafSAndrew Jeffery    # get DNS
518369419bafSAndrew Jeffery    parser_getDNS = nw_sub.add_parser("getDNS",
518469419bafSAndrew Jeffery                                      help="prints out DNS servers on the "
518569419bafSAndrew Jeffery                                      "given interface")
518669419bafSAndrew Jeffery    parser_getDNS.add_argument("-I", "--Interface", required=True,
518769419bafSAndrew Jeffery                               help="Name of the ethernet interface(it can"
518869419bafSAndrew Jeffery                               "be obtained by the "
518969419bafSAndrew Jeffery                               "command:network view-config)"
519069419bafSAndrew Jeffery                               "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
519169419bafSAndrew Jeffery    parser_getDNS.set_defaults(func=getDNS)
519269419bafSAndrew Jeffery
519369419bafSAndrew Jeffery    # set DNS
519469419bafSAndrew Jeffery    parser_setDNS = nw_sub.add_parser("setDNS",
519569419bafSAndrew Jeffery                                      help="sets DNS servers on the given "
519669419bafSAndrew Jeffery                                      "interface")
519769419bafSAndrew Jeffery    parser_setDNS.add_argument("-d", "--DNSServers", required=True,
519869419bafSAndrew Jeffery                               help="Ex: DNSSERVERS=DNS1,DNS2,...")
519969419bafSAndrew Jeffery    parser_setDNS.add_argument("-I", "--Interface", required=True,
520069419bafSAndrew Jeffery                               help="Name of the ethernet interface(it can"
520169419bafSAndrew Jeffery                               "be obtained by the "
520269419bafSAndrew Jeffery                               "command:network view-config)"
520369419bafSAndrew Jeffery                               "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
520469419bafSAndrew Jeffery    parser_setDNS.set_defaults(func=setDNS)
520569419bafSAndrew Jeffery
520669419bafSAndrew Jeffery    # get NTP
520769419bafSAndrew Jeffery    parser_getNTP = nw_sub.add_parser("getNTP",
520869419bafSAndrew Jeffery                                      help="prints out NTP servers on the "
520969419bafSAndrew Jeffery                                      "given interface")
521069419bafSAndrew Jeffery    parser_getNTP.add_argument("-I", "--Interface", required=True,
521169419bafSAndrew Jeffery                               help="Name of the ethernet interface(it can"
521269419bafSAndrew Jeffery                               "be obtained by the "
521369419bafSAndrew Jeffery                               "command:network view-config)"
521469419bafSAndrew Jeffery                               "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
521569419bafSAndrew Jeffery    parser_getNTP.set_defaults(func=getNTP)
521669419bafSAndrew Jeffery
521769419bafSAndrew Jeffery    # set NTP
521869419bafSAndrew Jeffery    parser_setNTP = nw_sub.add_parser("setNTP",
521969419bafSAndrew Jeffery                                      help="sets NTP servers on the given "
522069419bafSAndrew Jeffery                                      "interface")
522169419bafSAndrew Jeffery    parser_setNTP.add_argument("-N", "--NTPServers", required=True,
522269419bafSAndrew Jeffery                               help="Ex: NTPSERVERS=NTP1,NTP2,...")
522369419bafSAndrew Jeffery    parser_setNTP.add_argument("-I", "--Interface", required=True,
522469419bafSAndrew Jeffery                               help="Name of the ethernet interface(it can"
522569419bafSAndrew Jeffery                               "be obtained by the "
522669419bafSAndrew Jeffery                               "command:network view-config)"
522769419bafSAndrew Jeffery                               "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
522869419bafSAndrew Jeffery    parser_setNTP.set_defaults(func=setNTP)
522969419bafSAndrew Jeffery
523069419bafSAndrew Jeffery    # configure IP
523169419bafSAndrew Jeffery    parser_ip_config = nw_sub.add_parser("addIP", help="Sets IP address to"
523269419bafSAndrew Jeffery                                         "given interface")
523369419bafSAndrew Jeffery    parser_ip_config.add_argument("-a", "--address", required=True,
523469419bafSAndrew Jeffery                                  help="IP address of given interface")
523569419bafSAndrew Jeffery    parser_ip_config.add_argument("-gw", "--gateway", required=False, default='',
523669419bafSAndrew Jeffery                                  help="The gateway for given interface")
523769419bafSAndrew Jeffery    parser_ip_config.add_argument("-l", "--prefixLength", required=True,
523869419bafSAndrew Jeffery                                  help="The prefixLength of IP address")
523969419bafSAndrew Jeffery    parser_ip_config.add_argument("-p", "--type", required=True,
524069419bafSAndrew Jeffery                                  choices=['ipv4', 'ipv6'],
524169419bafSAndrew Jeffery                                  help="The protocol type of the given"
524269419bafSAndrew Jeffery                                  "IP address")
524369419bafSAndrew Jeffery    parser_ip_config.add_argument("-I", "--Interface", required=True,
524469419bafSAndrew Jeffery                                  help="Name of the ethernet interface(it can"
524569419bafSAndrew Jeffery                                  "be obtained by the "
524669419bafSAndrew Jeffery                                  "command:network view-config)"
524769419bafSAndrew Jeffery                                  "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
524869419bafSAndrew Jeffery    parser_ip_config.set_defaults(func=addIP)
524969419bafSAndrew Jeffery
525069419bafSAndrew Jeffery    # getIP
525169419bafSAndrew Jeffery    parser_getIP = nw_sub.add_parser("getIP", help="prints out IP address"
525269419bafSAndrew Jeffery                                     "of given interface")
525369419bafSAndrew Jeffery    parser_getIP.add_argument("-I", "--Interface", required=True,
525469419bafSAndrew Jeffery                              help="Name of the ethernet interface(it can"
525569419bafSAndrew Jeffery                              "be obtained by the command:network view-config)"
525669419bafSAndrew Jeffery                              "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
525769419bafSAndrew Jeffery    parser_getIP.set_defaults(func=getIP)
525869419bafSAndrew Jeffery
525969419bafSAndrew Jeffery    # rmIP
526069419bafSAndrew Jeffery    parser_rmIP = nw_sub.add_parser("rmIP", help="deletes IP address"
526169419bafSAndrew Jeffery                                     "of given interface")
526269419bafSAndrew Jeffery    parser_rmIP.add_argument("-a", "--address", required=True,
526369419bafSAndrew Jeffery                                  help="IP address to remove form given Interface")
526469419bafSAndrew Jeffery    parser_rmIP.add_argument("-I", "--Interface", required=True,
526569419bafSAndrew Jeffery                             help="Name of the ethernet interface(it can"
526669419bafSAndrew Jeffery                             "be obtained by the command:network view-config)"
526769419bafSAndrew Jeffery                             "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
526869419bafSAndrew Jeffery    parser_rmIP.set_defaults(func=deleteIP)
526969419bafSAndrew Jeffery
527069419bafSAndrew Jeffery    # add VLAN
527169419bafSAndrew Jeffery    parser_create_vlan = nw_sub.add_parser("addVLAN", help="enables VLAN "
527269419bafSAndrew Jeffery                                           "on given interface with given "
527369419bafSAndrew Jeffery                                           "VLAN Identifier")
527469419bafSAndrew Jeffery    parser_create_vlan.add_argument("-I", "--Interface", required=True,
527569419bafSAndrew Jeffery                                    choices=['eth0', 'eth1'],
527669419bafSAndrew Jeffery                                    help="Name of the ethernet interface")
527769419bafSAndrew Jeffery    parser_create_vlan.add_argument("-n", "--Identifier", required=True,
527869419bafSAndrew Jeffery                                  help="VLAN Identifier")
527969419bafSAndrew Jeffery    parser_create_vlan.set_defaults(func=addVLAN)
528069419bafSAndrew Jeffery
528169419bafSAndrew Jeffery    # delete VLAN
528269419bafSAndrew Jeffery    parser_delete_vlan = nw_sub.add_parser("deleteVLAN", help="disables VLAN "
528369419bafSAndrew Jeffery                                           "on given interface with given "
528469419bafSAndrew Jeffery                                           "VLAN Identifier")
528569419bafSAndrew Jeffery    parser_delete_vlan.add_argument("-I", "--Interface", required=True,
528669419bafSAndrew Jeffery                                    help="Name of the ethernet interface(it can"
528769419bafSAndrew Jeffery                                    "be obtained by the "
528869419bafSAndrew Jeffery                                    "command:network view-config)"
528969419bafSAndrew Jeffery                                    "Ex: eth0 or eth1 or VLAN(VLAN=eth0_50 etc)")
529069419bafSAndrew Jeffery    parser_delete_vlan.set_defaults(func=deleteVLAN)
529169419bafSAndrew Jeffery
529269419bafSAndrew Jeffery    # viewDHCPConfig
529369419bafSAndrew Jeffery    parser_viewDHCPConfig = nw_sub.add_parser("viewDHCPConfig",
529469419bafSAndrew Jeffery                                              help="Shows DHCP configured "
529569419bafSAndrew Jeffery                                              "Properties")
529669419bafSAndrew Jeffery    parser_viewDHCPConfig.set_defaults(func=viewDHCPConfig)
529769419bafSAndrew Jeffery
529869419bafSAndrew Jeffery    # configureDHCP
529969419bafSAndrew Jeffery    parser_configDHCP = nw_sub.add_parser("configureDHCP",
530069419bafSAndrew Jeffery                                          help="Configures/updates DHCP "
530169419bafSAndrew Jeffery                                          "Properties")
530269419bafSAndrew Jeffery    parser_configDHCP.add_argument("-d", "--DNSEnabled", type=str2bool,
530369419bafSAndrew Jeffery                                   required=True, help="Sets DNSEnabled property")
530469419bafSAndrew Jeffery    parser_configDHCP.add_argument("-n", "--HostNameEnabled", type=str2bool,
530569419bafSAndrew Jeffery                                   required=True,
530669419bafSAndrew Jeffery                                   help="Sets HostNameEnabled property")
530769419bafSAndrew Jeffery    parser_configDHCP.add_argument("-t", "--NTPEnabled", type=str2bool,
530869419bafSAndrew Jeffery                                   required=True,
530969419bafSAndrew Jeffery                                   help="Sets NTPEnabled property")
531069419bafSAndrew Jeffery    parser_configDHCP.add_argument("-s", "--SendHostNameEnabled", type=str2bool,
531169419bafSAndrew Jeffery                                   required=True,
531269419bafSAndrew Jeffery                                   help="Sets SendHostNameEnabled property")
531369419bafSAndrew Jeffery    parser_configDHCP.set_defaults(func=configureDHCP)
531469419bafSAndrew Jeffery
531569419bafSAndrew Jeffery    # network factory reset
531669419bafSAndrew Jeffery    parser_nw_reset = nw_sub.add_parser("nwReset",
531769419bafSAndrew Jeffery                                        help="Resets networks setting to "
531869419bafSAndrew Jeffery                                        "factory defaults. "
531969419bafSAndrew Jeffery                                        "note:Reset settings will be applied "
532069419bafSAndrew Jeffery                                        "after BMC reboot")
532169419bafSAndrew Jeffery    parser_nw_reset.set_defaults(func=nwReset)
532269419bafSAndrew Jeffery
532369419bafSAndrew Jeffery    return parser
532469419bafSAndrew Jeffery
532569419bafSAndrew Jefferydef main(argv=None):
532669419bafSAndrew Jeffery    """
532769419bafSAndrew Jeffery         main function for running the command line utility as a sub application
532869419bafSAndrew Jeffery    """
532969419bafSAndrew Jeffery    global toolVersion
533069419bafSAndrew Jeffery    toolVersion = "1.19"
533169419bafSAndrew Jeffery    global isRedfishSupport
533269419bafSAndrew Jeffery
533369419bafSAndrew Jeffery    parser = createCommandParser()
533469419bafSAndrew Jeffery    args = parser.parse_args(argv)
533569419bafSAndrew Jeffery
533669419bafSAndrew Jeffery    totTimeStart = int(round(time.time()*1000))
533769419bafSAndrew Jeffery
533869419bafSAndrew Jeffery    if(sys.version_info < (3,0)):
533969419bafSAndrew Jeffery        urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
534069419bafSAndrew Jeffery    if sys.version_info >= (3,0):
534169419bafSAndrew Jeffery        requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
534269419bafSAndrew Jeffery    if (args.version):
534369419bafSAndrew Jeffery        print("Version: "+ toolVersion)
534469419bafSAndrew Jeffery        sys.exit(0)
534569419bafSAndrew Jeffery    if (hasattr(args, 'fileloc') and args.fileloc is not None and 'print' in args.command):
534669419bafSAndrew Jeffery        mysess = None
534769419bafSAndrew Jeffery        print(selPrint('N/A', args, mysess))
534869419bafSAndrew Jeffery    else:
534969419bafSAndrew Jeffery        if(hasattr(args, 'host') and hasattr(args,'user')):
535069419bafSAndrew Jeffery            if (args.askpw):
535169419bafSAndrew Jeffery                pw = getpass.getpass()
535269419bafSAndrew Jeffery            elif(args.PW is not None):
535369419bafSAndrew Jeffery                pw = args.PW
535469419bafSAndrew Jeffery            elif(args.PWenvvar):
535569419bafSAndrew Jeffery                pw = os.environ['OPENBMCTOOL_PASSWORD']
535669419bafSAndrew Jeffery            else:
535769419bafSAndrew Jeffery                print("You must specify a password")
535869419bafSAndrew Jeffery                sys.exit()
535969419bafSAndrew Jeffery            logintimeStart = int(round(time.time()*1000))
536069419bafSAndrew Jeffery            mysess = login(args.host, args.user, pw, args.json,
536169419bafSAndrew Jeffery                           args.command == 'set_password')
536269419bafSAndrew Jeffery            if(mysess == None):
536369419bafSAndrew Jeffery                print("Login Failed!")
536469419bafSAndrew Jeffery                sys.exit()
536569419bafSAndrew Jeffery            if(sys.version_info < (3,0)):
536669419bafSAndrew Jeffery                if isinstance(mysess, basestring):
536769419bafSAndrew Jeffery                    print(mysess)
536869419bafSAndrew Jeffery                    sys.exit(1)
536969419bafSAndrew Jeffery            elif sys.version_info >= (3,0):
537069419bafSAndrew Jeffery                if isinstance(mysess, str):
537169419bafSAndrew Jeffery                    print(mysess)
537269419bafSAndrew Jeffery                    sys.exit(1)
537369419bafSAndrew Jeffery            logintimeStop = int(round(time.time()*1000))
537469419bafSAndrew Jeffery            isRedfishSupport = redfishSupportPresent(args.host,mysess)
537569419bafSAndrew Jeffery            commandTimeStart = int(round(time.time()*1000))
537669419bafSAndrew Jeffery            output = args.func(args.host, args, mysess)
537769419bafSAndrew Jeffery            commandTimeStop = int(round(time.time()*1000))
537869419bafSAndrew Jeffery            if isinstance(output, dict):
537969419bafSAndrew Jeffery                print(json.dumps(output, sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False))
538069419bafSAndrew Jeffery            else:
538169419bafSAndrew Jeffery                print(output)
538269419bafSAndrew Jeffery            if (mysess is not None):
538369419bafSAndrew Jeffery                logout(args.host, args.user, pw, mysess, args.json)
538469419bafSAndrew Jeffery            if(args.procTime):
538569419bafSAndrew Jeffery                print("Total time: " + str(int(round(time.time()*1000))- totTimeStart))
538669419bafSAndrew Jeffery                print("loginTime: " + str(logintimeStop - logintimeStart))
538769419bafSAndrew Jeffery                print("command Time: " + str(commandTimeStop - commandTimeStart))
538869419bafSAndrew Jeffery        else:
538969419bafSAndrew Jeffery            print("usage:\n"
539069419bafSAndrew Jeffery                  "  OPENBMCTOOL_PASSWORD=secret  # if using -E\n"
539169419bafSAndrew Jeffery                  "  openbmctool.py [-h] -H HOST -U USER {-A | -P PW | -E} [-j]\n" +
539269419bafSAndrew Jeffery                      "\t[-t POLICYTABLELOC] [-V]\n" +
539369419bafSAndrew Jeffery                      "\t{fru,sensors,sel,chassis,collect_service_data, \
539469419bafSAndrew Jeffery                          health_check,dump,bmc,mc,gardclear,firmware,logging}\n" +
539569419bafSAndrew Jeffery                      "\t...\n" +
539669419bafSAndrew Jeffery                      "openbmctool.py: error: the following arguments are required: -H/--host, -U/--user")
539769419bafSAndrew Jeffery            sys.exit()
539869419bafSAndrew Jeffery
539969419bafSAndrew Jefferyif __name__ == '__main__':
540069419bafSAndrew Jeffery    """
540169419bafSAndrew Jeffery         main function when called from the command line
540269419bafSAndrew Jeffery
540369419bafSAndrew Jeffery    """
540469419bafSAndrew Jeffery    import sys
540569419bafSAndrew Jeffery
540669419bafSAndrew Jeffery    isTTY = sys.stdout.isatty()
540769419bafSAndrew Jeffery    assert sys.version_info >= (2,7)
540869419bafSAndrew Jeffery    main()
5409