{"action":"created","comment":{"url":"https://api.github.com/repos/openbmc/openbmc-tools/pulls/comments/157121985","pull_request_review_id":83709770,"id":157121985,"diff_hunk":"@@ -0,0 +1,1490 @@\n+#!/usr/bin/python3\n+\n+'''\n+#================================================================================\n+#\n+#    openbmctool.py\n+#\n+#    Copyright IBM Corporation 2015-2017. All Rights Reserved\n+#\n+#    This program is licensed under the terms of the Eclipse Public License\n+#    v1.0 as published by the Eclipse Foundation and available at\n+#    http://www.eclipse.org/legal/epl-v10.html\n+#\n+#    U.S. Government Users Restricted Rights:  Use, duplication or disclosure\n+#    restricted by GSA ADP Schedule Contract with IBM Corp.\n+#\n+#================================================================================\n+'''\n+import argparse\n+import requests\n+import getpass\n+import json\n+import os\n+import urllib3\n+import time, datetime\n+# import yaml\n+import binascii\n+import subprocess\n+import platform\n+import zipfile\n+\n+#isTTY = sys.stdout.isatty()\n+\n+\"\"\"\n+     Used to add highlights to various text for displaying in a terminal\n+       \n+     @param textToColor: string, the text to be colored\n+     @param color: string, used to color the text red or green\n+     @param bold: boolean, used to bold the textToColor\n+     @return: Buffered reader containing the modified string. \n+\"\"\"    \n+def hilight(textToColor, color, bold):\n+    if(sys.platform.__contains__(\"win\")):\n+        if(color == \"red\"):\n+            os.system('color 04')\n+        elif(color == \"green\"):\n+            os.system('color 02')\n+        else:\n+            os.system('color') #reset to default\n+        return textToColor\n+    else:\n+        attr = []\n+        if(color == \"red\"):\n+            attr.append('31')\n+        elif(color == \"green\"):\n+            attr.append('32')\n+        else:\n+            attr.append('0')\n+        if bold:\n+            attr.append('1')\n+        else:\n+            attr.append('0')\n+        return '\\x1b[%sm%s\\x1b[0m' % (';'.join(attr),textToColor)\n+\n+\"\"\"\n+     Error handler various connection errors to bmcs\n+       \n+     @param jsonFormat: boolean, used to output in json format with an error code. \n+     @param errorStr: string, used to color the text red or green\n+     @param err: string, the text from the exception \n+\"\"\"    \n+def connectionErrHandler(jsonFormat, errorStr, err):\n+    if errorStr == \"Timeout\":\n+        if not jsonFormat:\n+            return(\"FQPSPIN0000M: Connection timed out. Ensure you have network connectivity to the bmc\")\n+        else:\n+            errorMessageStr = (\"{\\n\\t\\\"event0\\\":{\\n\" +\n+            \"\\t\\t\\\"CommonEventID\\\": \\\"FQPSPIN0000M\\\",\\n\"+\n+            \"\\t\\t\\\"sensor\\\": \\\"N/A\\\",\\n\"+\n+            \"\\t\\t\\\"state\\\": \\\"N/A\\\",\\n\" +\n+            \"\\t\\t\\\"additionalDetails\\\": \\\"N/A\\\",\\n\" +\n+            \"\\t\\t\\\"Message\\\": \\\"Connection timed out. Ensure you have network connectivity to the BMC\\\",\\n\" +\n+            \"\\t\\t\\\"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.\\\",\\n\" +\n+            \"\\t\\t\\\"Serviceable\\\": \\\"Yes\\\",\\n\" +\n+            \"\\t\\t\\\"CallHomeCandidate\\\": \\\"No\\\",\\n\" +\n+            \"\\t\\t\\\"Severity\\\": \\\"Critical\\\",\\n\" +\n+            \"\\t\\t\\\"EventType\\\": \\\"Communication Failure/Timeout\\\",\\n\" +\n+            \"\\t\\t\\\"VMMigrationFlag\\\": \\\"Yes\\\",\\n\" +\n+            \"\\t\\t\\\"AffectedSubsystem\\\": \\\"Interconnect (Networking)\\\",\\n\" +\n+            \"\\t\\t\\\"timestamp\\\": \\\"\"+str(int(time.time()))+\"\\\",\\n\" +\n+            \"\\t\\t\\\"UserAction\\\": \\\"Verify network connectivity between the two systems and the bmc is functional.\\\"\" +\n+            \"\\t\\n}, \\n\" +\n+            \"\\t\\\"numAlerts\\\": \\\"1\\\" \\n}\");\n+            return(errorMessageStr)\n+    elif errorStr == \"ConnectionError\":\n+        if not jsonFormat:\n+            return(\"FQPSPIN0001M: \" + str(err))\n+        else:\n+            errorMessageStr = (\"{\\n\\t\\\"event0\\\":{\\n\" +\n+            \"\\t\\t\\\"CommonEventID\\\": \\\"FQPSPIN0001M\\\",\\n\"+\n+            \"\\t\\t\\\"sensor\\\": \\\"N/A\\\",\\n\"+\n+            \"\\t\\t\\\"state\\\": \\\"N/A\\\",\\n\" +\n+            \"\\t\\t\\\"additionalDetails\\\": \\\"\" + str(err)+\"\\\",\\n\" +\n+            \"\\t\\t\\\"Message\\\": \\\"Connection Error. View additional details for more information\\\",\\n\" +\n+            \"\\t\\t\\\"LengthyDescription\\\": \\\"A connection error to the specified BMC occurred and additional details are provided. Review these details to resolve the issue.\\\",\\n\" +\n+            \"\\t\\t\\\"Serviceable\\\": \\\"Yes\\\",\\n\" +\n+            \"\\t\\t\\\"CallHomeCandidate\\\": \\\"No\\\",\\n\" +\n+            \"\\t\\t\\\"Severity\\\": \\\"Critical\\\",\\n\" +\n+            \"\\t\\t\\\"EventType\\\": \\\"Communication Failure/Timeout\\\",\\n\" +\n+            \"\\t\\t\\\"VMMigrationFlag\\\": \\\"Yes\\\",\\n\" +\n+            \"\\t\\t\\\"AffectedSubsystem\\\": \\\"Interconnect (Networking)\\\",\\n\" +\n+            \"\\t\\t\\\"timestamp\\\": \\\"\"+str(int(time.time()))+\"\\\",\\n\" +\n+            \"\\t\\t\\\"UserAction\\\": \\\"Correct the issue highlighted in additional details and try again\\\"\" +\n+            \"\\t\\n}, \\n\" +\n+            \"\\t\\\"numAlerts\\\": \\\"1\\\" \\n}\");\n+            return(errorMessageStr)\n+    else:\n+        return(\"Unknown Error: \"+ str(err))\n+\n+\"\"\"\n+     Sets the output width of the columns to display\n+       \n+     @param keylist: list, list of strings representing the keys for the dictForOutput \n+     @param numcols: the total number of columns in the final output\n+     @param dictForOutput: dictionary, contains the information to print to the screen\n+     @param colNames: list, The strings to use for the column headings, in order of the keylist\n+     @return: A list of the column widths for each respective column. \n+\"\"\"\n+def setColWidth(keylist, numCols, dictForOutput, colNames):\n+    colWidths = []\n+    for x in range(0, numCols):\n+        colWidths.append(0)\n+    for key in dictForOutput:\n+        for x in range(0, numCols):\n+            colWidths[x] = max(colWidths[x], len(str(dictForOutput[key][keylist[x]])))\n+    \n+    for x in range(0, numCols):\n+        colWidths[x] = max(colWidths[x], len(colNames[x])) +2\n+    \n+    return colWidths\n+\n+def loadPolicyTable(pathToPolicyTable):\n+    policyTable = {}\n+    if(os.path.exists(pathToPolicyTable)):\n+        with open(pathToPolicyTable, 'r') as stream:\n+            try:\n+#                 contents = yaml.load(stream)\n+                contents =json.load(stream)\n+                policyTable = contents['events']\n+            except yaml.YAMLError as err:\n+                print(err)\n+    return policyTable\n+\n+\"\"\"\n+     Logs into the BMC and creates a session\n+       \n+     @param host: string, the hostname or IP address of the bmc to log into\n+     @param username: The user name for the bmc to log into\n+     @param pw: The password for the BMC to log into\n+     @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true. \n+     @return: Session object\n+\"\"\"\n+def login(host, username, pw,jsonFormat):\n+    if(jsonFormat==False):\n+        print(\"Attempting login...\")\n+    httpHeader = {'Content-Type':'application/json'}\n+    mysess = requests.session()\n+    try:\n+        r = mysess.post('https://'+host+'/login', headers=httpHeader, json = {\"data\": [username, pw]}, verify=False, timeout=30)\n+        loginMessage = json.loads(r.text)\n+        if (loginMessage['status'] != \"ok\"):\n+            print(loginMessage[\"data\"][\"description\"].encode('utf-8')) \n+            sys.exit(1)\n+#         if(sys.version_info < (3,0)):\n+#             urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)\n+#         if sys.version_info >= (3,0):\n+#             requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)\n+        return mysess\n+    except(requests.exceptions.Timeout):\n+        print(connectionErrHandler(jsonFormat, \"Timeout\", None))\n+        sys.exit(1)\n+    except(requests.exceptions.ConnectionError) as err:\n+        print(connectionErrHandler(jsonFormat, \"ConnectionError\", err))\n+        sys.exit(1)\n+\n+\"\"\"\n+     Logs out of the bmc and terminates the session\n+       \n+     @param host: string, the hostname or IP address of the bmc to log out of\n+     @param username: The user name for the bmc to log out of\n+     @param pw: The password for the BMC to log out of\n+     @param session: the active session to use\n+     @param jsonFormat: boolean, flag that will only allow relevant data from user command to be display. This function becomes silent when set to true. \n+\"\"\"    \n+def logout(host, username, pw, session, jsonFormat):\n+    httpHeader = {'Content-Type':'application/json'}\n+    r = session.post('https://'+host+'/logout', headers=httpHeader,json = {\"data\": [username, pw]}, verify=False, timeout=10)\n+    if(jsonFormat==False):\n+        if('\"message\": \"200 OK\"' in r.text):\n+            print('User ' +username + ' has been logged out')\n+\n+\"\"\"\n+     prints out the system inventory. deprecated see fruPrint and fruList\n+       \n+     @param host: string, the hostname or IP address of the bmc\n+     @param args: contains additional arguments used by the fru sub command\n+     @param session: the active session to use\n+     @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption \n+\"\"\"   \n+def fru(host, args, session):\n+    #url=\"https://\"+host+\"/org/openbmc/inventory/system/chassis/enumerate\"\n+    \n+    #print(url)\n+    #res = session.get(url, headers=httpHeader, verify=False)\n+    #print(res.text)\n+    #sample = res.text\n+    \n+    #inv_list = json.loads(sample)[\"data\"]\n+    \n+    url=\"https://\"+host+\"/xyz/openbmc_project/inventory/enumerate\"\n+    httpHeader = {'Content-Type':'application/json'}\n+    res = session.get(url, headers=httpHeader, verify=False)\n+    sample = res.text\n+#     inv_list.update(json.loads(sample)[\"data\"])\n+#     \n+#     #determine column width's\n+#     colNames = [\"FRU Name\", \"FRU Type\", \"Has Fault\", \"Is FRU\", \"Present\", \"Version\"]\n+#     colWidths = setColWidth([\"FRU Name\", \"fru_type\", \"fault\", \"is_fru\", \"present\", \"version\"], 6, inv_list, colNames)\n+#    \n+#     print(\"FRU Name\".ljust(colWidths[0])+ \"FRU Type\".ljust(colWidths[1]) + \"Has Fault\".ljust(colWidths[2]) + \"Is FRU\".ljust(colWidths[3])+ \n+#           \"Present\".ljust(colWidths[4]) + \"Version\".ljust(colWidths[5]))\n+#     format the output\n+#     for key in sorted(inv_list.keys()):\n+#         keyParts = key.split(\"/\")\n+#         isFRU = \"True\" if (inv_list[key][\"is_fru\"]==1) else \"False\"\n+#         \n+#         fruEntry = (keyParts[len(keyParts) - 1].ljust(colWidths[0]) + inv_list[key][\"fru_type\"].ljust(colWidths[1])+\n+#                inv_list[key][\"fault\"].ljust(colWidths[2])+isFRU.ljust(colWidths[3])+\n+#                inv_list[key][\"present\"].ljust(colWidths[4])+ inv_list[key][\"version\"].ljust(colWidths[5]))\n+#         if(isTTY):\n+#             if(inv_list[key][\"is_fru\"] == 1):\n+#                 color = \"green\"\n+#                 bold = True\n+#             else:\n+#                 color='black'\n+#                 bold = False\n+#             fruEntry = hilight(fruEntry, color, bold)\n+#         print (fruEntry)\n+    return sample\n+\"\"\"\n+     prints out all inventory\n+       \n+     @param host: string, the hostname or IP address of the bmc\n+     @param args: contains additional arguments used by the fru sub command\n+     @param session: the active session to use\n+     @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption \n+     @return returns the total fru list. \n+\"\"\" \n+def fruPrint(host, args, session):   \n+    url=\"https://\"+host+\"/xyz/openbmc_project/inventory/enumerate\"\n+    httpHeader = {'Content-Type':'application/json'}\n+    res = session.get(url, headers=httpHeader, verify=False)\n+#     print(res.text)\n+    frulist = res.text\n+    url=\"https://\"+host+\"/xyz/openbmc_project/software/enumerate\"\n+    res = session.get(url, headers=httpHeader, verify=False)\n+#     print(res.text)\n+    frulist = frulist +\"\\n\" + res.text\n+    \n+    return frulist\n+\n+\"\"\"\n+     prints out all inventory or only a specific specified item\n+       \n+     @param host: string, the hostname or IP address of the bmc\n+     @param args: contains additional arguments used by the fru sub command\n+     @param session: the active session to use\n+     @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption \n+\"\"\" \n+def fruList(host, args, session):\n+    if(args.items==True):\n+        return fruPrint(host, args, session)\n+    else:\n+        return \"not implemented at this time\"\n+\n+\n+\"\"\"\n+     prints out the status of all FRUs\n+       \n+     @param host: string, the hostname or IP address of the bmc\n+     @param args: contains additional arguments used by the fru sub command\n+     @param session: the active session to use\n+     @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption \n+\"\"\"         \n+def fruStatus(host, args, session):\n+    print(\"fru status to be implemented\")\n+\n+\"\"\"\n+     prints out all sensors\n+       \n+     @param host: string, the hostname or IP address of the bmc\n+     @param args: contains additional arguments used by the sensor sub command\n+     @param session: the active session to use\n+     @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption \n+\"\"\"        \n+def sensor(host, args, session):\n+#     url=\"https://\"+host+\"/org/openbmc/sensors/enumerate\"\n+    httpHeader = {'Content-Type':'application/json'}\n+#     print(url)\n+#     res = session.get(url, headers=httpHeader, verify=False, timeout=20)\n+#     print(res.text)\n+    url=\"https://\"+host+\"/xyz/openbmc_project/sensors/enumerate\"\n+    res = session.get(url, headers=httpHeader, verify=False, timeout=20)\n+    \n+    #Get OCC status\n+    url=\"https://\"+host+\"/org/open_power/control/enumerate\"\n+    occres = session.get(url, headers=httpHeader, verify=False, timeout=20)\n+    if not args.json:\n+        colNames = ['sensor', 'type', 'units', 'value', 'target']\n+        sensors = json.loads(res.text)[\"data\"]\n+        output = {}\n+        for key in sensors:\n+            senDict = {}\n+            keyparts = key.split(\"/\")\n+            senDict['sensorName'] = keyparts[-1]\n+            senDict['type'] = keyparts[-2]\n+            senDict['units'] = sensors[key]['Unit'].split('.')[-1]\n+            if('Scale' in sensors[key]): \n+                scale = 10 ** sensors[key]['Scale'] \n+            else: \n+                scale = 1\n+            senDict['value'] = str(sensors[key]['Value'] * scale)\n+            if 'Target' in sensors[key]:\n+                senDict['target'] = str(sensors[key]['Target'])\n+            else:\n+                senDict['target'] = 'N/A'\n+            output[senDict['sensorName']] = senDict\n+        \n+        occstatus = json.loads(occres.text)[\"data\"]\n+        if '/org/open_power/control/occ0' in occstatus:\n+            occ0 = occstatus[\"/org/open_power/control/occ0\"]['OccActive']\n+            if occ0 == 1: \n+                occ0 = 'Active' \n+            else: \n+                occ0 = 'Inactive'\n+            output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}\n+            occ1 = occstatus[\"/org/open_power/control/occ1\"]['OccActive']\n+            if occ1 == 1: \n+                occ1 = 'Active' \n+            else: \n+                occ1 = 'Inactive'\n+            output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': occ0, 'target': 'Active'}\n+        else:\n+            output['OCC0'] = {'sensorName':'OCC0', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}\n+            output['OCC1'] = {'sensorName':'OCC1', 'type': 'Discrete', 'units': 'N/A', 'value': 'Inactive', 'target': 'Inactive'}\n+        keylist = ['sensorName', 'type', 'units', 'value', 'target']\n+        colWidth = setColWidth(keylist, len(colNames), output, colNames)\n+        row = \"\"\n+        outputText = \"\"\n+        for i in range(len(colNames)):\n+            if (i != 0): row = row + \"| \"\n+            row = row + colNames[i].ljust(colWidth[i])\n+        outputText += row + \"\\n\"\n+        sortedKeys = list(output.keys()).sort\n+        for key in sorted(output.keys()):\n+            row = \"\"\n+            for i in range(len(output[key])):\n+                if (i != 0): row = row + \"| \"\n+                row = row + output[key][keylist[i]].ljust(colWidth[i])\n+            outputText += row + \"\\n\"\n+        return outputText\n+    else:\n+        return res.text + occres.text\n+\"\"\"\n+     prints out the bmc alerts\n+       \n+     @param host: string, the hostname or IP address of the bmc\n+     @param args: contains additional arguments used by the sel sub command\n+     @param session: the active session to use\n+     @param args.json: boolean, if this flag is set to true, the output will be provided in json format for programmatic consumption \n+\"\"\"     \n+def sel(host, args, session):\n+\n+    url=\"https://\"+host+\"/xyz/openbmc_project/logging/entry/enumerate\"\n+    httpHeader = {'Content-Type':'application/json'}\n+    #print(url)\n+    res = session.get(url, headers=httpHeader, verify=False, timeout=60)\n+    return res.text\n+\n+\n+\"\"\"\n+     converts a boolean value to a human readable string value\n+       \n+     @param value: boolean, the value to convert\n+     @return: A string of \"Yes\" or \"No\"\n+\"\"\" \n+def boolToString(value):\n+    if(value):\n+        return \"Yes\"\n+    else:\n+        return \"No\"\n+    \n+\"\"\"\n+     parses the esel data and gets predetermined search terms\n+       \n+     @param eselRAW: string, the raw esel string from the bmc\n+     @return: A dictionary containing the quick snapshot data unless args.fullEsel is listed then a full PEL log is returned\n+\"\"\"    \n+def parseESEL(args, eselRAW):\n+    eselParts = {}\n+    esel_bin = binascii.unhexlify(''.join(eselRAW.split()[16:]))\n+    #search terms contains the search term as the key and the return dictionary key as it's value\n+    searchTerms = { 'Signature Description':'signatureDescription', 'devdesc':'devdesc',\n+                    'Callout type': 'calloutType', 'Procedure':'procedure'}\n+    \n+    with open('/tmp/esel.bin', 'wb') as f:\n+        f.write(esel_bin)\n+    errlPath = \"\"\n+    #use the right errl file for the machine architecture\n+    arch = platform.machine()\n+    if(arch =='x86_64' or arch =='AMD64'):","path":"thalerj/openbmctool.py","position":421,"original_position":421,"commit_id":"f9aee3e5bb90c854eb6ac48426caee098ecd3b7c","original_commit_id":"f9aee3e5bb90c854eb6ac48426caee098ecd3b7c","user":{"login":"amboar","id":526481,"avatar_url":"https://avatars0.githubusercontent.com/u/526481?v=4","gravatar_id":"","url":"https://api.github.com/users/amboar","html_url":"https://github.com/amboar","followers_url":"https://api.github.com/users/amboar/followers","following_url":"https://api.github.com/users/amboar/following{/other_user}","gists_url":"https://api.github.com/users/amboar/gists{/gist_id}","starred_url":"https://api.github.com/users/amboar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amboar/subscriptions","organizations_url":"https://api.github.com/users/amboar/orgs","repos_url":"https://api.github.com/users/amboar/repos","events_url":"https://api.github.com/users/amboar/events{/privacy}","received_events_url":"https://api.github.com/users/amboar/received_events","type":"User","site_admin":false},"body":"Can't we just pass an option to the tool pointing to the errl file? Also i feel like discovery of the file should be it's own function","created_at":"2017-12-15T04:27:33Z","updated_at":"2017-12-15T04:49:39Z","html_url":"https://github.com/openbmc/openbmc-tools/pull/4#discussion_r157121985","pull_request_url":"https://api.github.com/repos/openbmc/openbmc-tools/pulls/4","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/openbmc/openbmc-tools/pulls/comments/157121985"},"html":{"href":"https://github.com/openbmc/openbmc-tools/pull/4#discussion_r157121985"},"pull_request":{"href":"https://api.github.com/repos/openbmc/openbmc-tools/pulls/4"}}},"pull_request":{"url":"https://api.github.com/repos/openbmc/openbmc-tools/pulls/4","id":156536068,"html_url":"https://github.com/openbmc/openbmc-tools/pull/4","diff_url":"https://github.com/openbmc/openbmc-tools/pull/4.diff","patch_url":"https://github.com/openbmc/openbmc-tools/pull/4.patch","issue_url":"https://api.github.com/repos/openbmc/openbmc-tools/issues/4","number":4,"state":"open","locked":false,"title":"Adding openbmctool","user":{"login":"thalerj","id":17790561,"avatar_url":"https://avatars0.githubusercontent.com/u/17790561?v=4","gravatar_id":"","url":"https://api.github.com/users/thalerj","html_url":"https://github.com/thalerj","followers_url":"https://api.github.com/users/thalerj/followers","following_url":"https://api.github.com/users/thalerj/following{/other_user}","gists_url":"https://api.github.com/users/thalerj/gists{/gist_id}","starred_url":"https://api.github.com/users/thalerj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thalerj/subscriptions","organizations_url":"https://api.github.com/users/thalerj/orgs","repos_url":"https://api.github.com/users/thalerj/repos","events_url":"https://api.github.com/users/thalerj/events{/privacy}","received_events_url":"https://api.github.com/users/thalerj/received_events","type":"User","site_admin":false},"body":"Adding the openbmctool to this repository as requested. ","created_at":"2017-12-05T18:12:21Z","updated_at":"2017-12-15T04:49:39Z","closed_at":null,"merged_at":null,"merge_commit_sha":"cfd3e2eb78a0c70e13a80c31b4653f5de14f628c","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/openbmc/openbmc-tools/pulls/4/commits","review_comments_url":"https://api.github.com/repos/openbmc/openbmc-tools/pulls/4/comments","review_comment_url":"https://api.github.com/repos/openbmc/openbmc-tools/pulls/comments{/number}","comments_url":"https://api.github.com/repos/openbmc/openbmc-tools/issues/4/comments","statuses_url":"https://api.github.com/repos/openbmc/openbmc-tools/statuses/f9aee3e5bb90c854eb6ac48426caee098ecd3b7c","head":{"label":"thalerj:master","ref":"master","sha":"f9aee3e5bb90c854eb6ac48426caee098ecd3b7c","user":{"login":"thalerj","id":17790561,"avatar_url":"https://avatars0.githubusercontent.com/u/17790561?v=4","gravatar_id":"","url":"https://api.github.com/users/thalerj","html_url":"https://github.com/thalerj","followers_url":"https://api.github.com/users/thalerj/followers","following_url":"https://api.github.com/users/thalerj/following{/other_user}","gists_url":"https://api.github.com/users/thalerj/gists{/gist_id}","starred_url":"https://api.github.com/users/thalerj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thalerj/subscriptions","organizations_url":"https://api.github.com/users/thalerj/orgs","repos_url":"https://api.github.com/users/thalerj/repos","events_url":"https://api.github.com/users/thalerj/events{/privacy}","received_events_url":"https://api.github.com/users/thalerj/received_events","type":"User","site_admin":false},"repo":{"id":113215575,"name":"openbmc-tools","full_name":"thalerj/openbmc-tools","owner":{"login":"thalerj","id":17790561,"avatar_url":"https://avatars0.githubusercontent.com/u/17790561?v=4","gravatar_id":"","url":"https://api.github.com/users/thalerj","html_url":"https://github.com/thalerj","followers_url":"https://api.github.com/users/thalerj/followers","following_url":"https://api.github.com/users/thalerj/following{/other_user}","gists_url":"https://api.github.com/users/thalerj/gists{/gist_id}","starred_url":"https://api.github.com/users/thalerj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thalerj/subscriptions","organizations_url":"https://api.github.com/users/thalerj/orgs","repos_url":"https://api.github.com/users/thalerj/repos","events_url":"https://api.github.com/users/thalerj/events{/privacy}","received_events_url":"https://api.github.com/users/thalerj/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/thalerj/openbmc-tools","description":"Collection of useful tools to interact with openbmc","fork":true,"url":"https://api.github.com/repos/thalerj/openbmc-tools","forks_url":"https://api.github.com/repos/thalerj/openbmc-tools/forks","keys_url":"https://api.github.com/repos/thalerj/openbmc-tools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/thalerj/openbmc-tools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/thalerj/openbmc-tools/teams","hooks_url":"https://api.github.com/repos/thalerj/openbmc-tools/hooks","issue_events_url":"https://api.github.com/repos/thalerj/openbmc-tools/issues/events{/number}","events_url":"https://api.github.com/repos/thalerj/openbmc-tools/events","assignees_url":"https://api.github.com/repos/thalerj/openbmc-tools/assignees{/user}","branches_url":"https://api.github.com/repos/thalerj/openbmc-tools/branches{/branch}","tags_url":"https://api.github.com/repos/thalerj/openbmc-tools/tags","blobs_url":"https://api.github.com/repos/thalerj/openbmc-tools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/thalerj/openbmc-tools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/thalerj/openbmc-tools/git/refs{/sha}","trees_url":"https://api.github.com/repos/thalerj/openbmc-tools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/thalerj/openbmc-tools/statuses/{sha}","languages_url":"https://api.github.com/repos/thalerj/openbmc-tools/languages","stargazers_url":"https://api.github.com/repos/thalerj/openbmc-tools/stargazers","contributors_url":"https://api.github.com/repos/thalerj/openbmc-tools/contributors","subscribers_url":"https://api.github.com/repos/thalerj/openbmc-tools/subscribers","subscription_url":"https://api.github.com/repos/thalerj/openbmc-tools/subscription","commits_url":"https://api.github.com/repos/thalerj/openbmc-tools/commits{/sha}","git_commits_url":"https://api.github.com/repos/thalerj/openbmc-tools/git/commits{/sha}","comments_url":"https://api.github.com/repos/thalerj/openbmc-tools/comments{/number}","issue_comment_url":"https://api.github.com/repos/thalerj/openbmc-tools/issues/comments{/number}","contents_url":"https://api.github.com/repos/thalerj/openbmc-tools/contents/{+path}","compare_url":"https://api.github.com/repos/thalerj/openbmc-tools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/thalerj/openbmc-tools/merges","archive_url":"https://api.github.com/repos/thalerj/openbmc-tools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/thalerj/openbmc-tools/downloads","issues_url":"https://api.github.com/repos/thalerj/openbmc-tools/issues{/number}","pulls_url":"https://api.github.com/repos/thalerj/openbmc-tools/pulls{/number}","milestones_url":"https://api.github.com/repos/thalerj/openbmc-tools/milestones{/number}","notifications_url":"https://api.github.com/repos/thalerj/openbmc-tools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/thalerj/openbmc-tools/labels{/name}","releases_url":"https://api.github.com/repos/thalerj/openbmc-tools/releases{/id}","deployments_url":"https://api.github.com/repos/thalerj/openbmc-tools/deployments","created_at":"2017-12-05T17:59:35Z","updated_at":"2017-12-05T17:59:36Z","pushed_at":"2017-12-05T18:11:20Z","git_url":"git://github.com/thalerj/openbmc-tools.git","ssh_url":"git@github.com:thalerj/openbmc-tools.git","clone_url":"https://github.com/thalerj/openbmc-tools.git","svn_url":"https://github.com/thalerj/openbmc-tools","homepage":null,"size":65,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"openbmc:master","ref":"master","sha":"c2ea03ed6ed294f699de14a9e20d436e77b896b5","user":{"login":"openbmc","id":13670043,"avatar_url":"https://avatars2.githubusercontent.com/u/13670043?v=4","gravatar_id":"","url":"https://api.github.com/users/openbmc","html_url":"https://github.com/openbmc","followers_url":"https://api.github.com/users/openbmc/followers","following_url":"https://api.github.com/users/openbmc/following{/other_user}","gists_url":"https://api.github.com/users/openbmc/gists{/gist_id}","starred_url":"https://api.github.com/users/openbmc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openbmc/subscriptions","organizations_url":"https://api.github.com/users/openbmc/orgs","repos_url":"https://api.github.com/users/openbmc/repos","events_url":"https://api.github.com/users/openbmc/events{/privacy}","received_events_url":"https://api.github.com/users/openbmc/received_events","type":"Organization","site_admin":false},"repo":{"id":106747877,"name":"openbmc-tools","full_name":"openbmc/openbmc-tools","owner":{"login":"openbmc","id":13670043,"avatar_url":"https://avatars2.githubusercontent.com/u/13670043?v=4","gravatar_id":"","url":"https://api.github.com/users/openbmc","html_url":"https://github.com/openbmc","followers_url":"https://api.github.com/users/openbmc/followers","following_url":"https://api.github.com/users/openbmc/following{/other_user}","gists_url":"https://api.github.com/users/openbmc/gists{/gist_id}","starred_url":"https://api.github.com/users/openbmc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openbmc/subscriptions","organizations_url":"https://api.github.com/users/openbmc/orgs","repos_url":"https://api.github.com/users/openbmc/repos","events_url":"https://api.github.com/users/openbmc/events{/privacy}","received_events_url":"https://api.github.com/users/openbmc/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/openbmc/openbmc-tools","description":"Collection of useful tools to interact with openbmc","fork":false,"url":"https://api.github.com/repos/openbmc/openbmc-tools","forks_url":"https://api.github.com/repos/openbmc/openbmc-tools/forks","keys_url":"https://api.github.com/repos/openbmc/openbmc-tools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/openbmc/openbmc-tools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/openbmc/openbmc-tools/teams","hooks_url":"https://api.github.com/repos/openbmc/openbmc-tools/hooks","issue_events_url":"https://api.github.com/repos/openbmc/openbmc-tools/issues/events{/number}","events_url":"https://api.github.com/repos/openbmc/openbmc-tools/events","assignees_url":"https://api.github.com/repos/openbmc/openbmc-tools/assignees{/user}","branches_url":"https://api.github.com/repos/openbmc/openbmc-tools/branches{/branch}","tags_url":"https://api.github.com/repos/openbmc/openbmc-tools/tags","blobs_url":"https://api.github.com/repos/openbmc/openbmc-tools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/openbmc/openbmc-tools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/openbmc/openbmc-tools/git/refs{/sha}","trees_url":"https://api.github.com/repos/openbmc/openbmc-tools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/openbmc/openbmc-tools/statuses/{sha}","languages_url":"https://api.github.com/repos/openbmc/openbmc-tools/languages","stargazers_url":"https://api.github.com/repos/openbmc/openbmc-tools/stargazers","contributors_url":"https://api.github.com/repos/openbmc/openbmc-tools/contributors","subscribers_url":"https://api.github.com/repos/openbmc/openbmc-tools/subscribers","subscription_url":"https://api.github.com/repos/openbmc/openbmc-tools/subscription","commits_url":"https://api.github.com/repos/openbmc/openbmc-tools/commits{/sha}","git_commits_url":"https://api.github.com/repos/openbmc/openbmc-tools/git/commits{/sha}","comments_url":"https://api.github.com/repos/openbmc/openbmc-tools/comments{/number}","issue_comment_url":"https://api.github.com/repos/openbmc/openbmc-tools/issues/comments{/number}","contents_url":"https://api.github.com/repos/openbmc/openbmc-tools/contents/{+path}","compare_url":"https://api.github.com/repos/openbmc/openbmc-tools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/openbmc/openbmc-tools/merges","archive_url":"https://api.github.com/repos/openbmc/openbmc-tools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/openbmc/openbmc-tools/downloads","issues_url":"https://api.github.com/repos/openbmc/openbmc-tools/issues{/number}","pulls_url":"https://api.github.com/repos/openbmc/openbmc-tools/pulls{/number}","milestones_url":"https://api.github.com/repos/openbmc/openbmc-tools/milestones{/number}","notifications_url":"https://api.github.com/repos/openbmc/openbmc-tools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/openbmc/openbmc-tools/labels{/name}","releases_url":"https://api.github.com/repos/openbmc/openbmc-tools/releases{/id}","deployments_url":"https://api.github.com/repos/openbmc/openbmc-tools/deployments","created_at":"2017-10-12T21:36:22Z","updated_at":"2017-12-01T19:36:27Z","pushed_at":"2017-12-05T18:12:22Z","git_url":"git://github.com/openbmc/openbmc-tools.git","ssh_url":"git@github.com:openbmc/openbmc-tools.git","clone_url":"https://github.com/openbmc/openbmc-tools.git","svn_url":"https://github.com/openbmc/openbmc-tools","homepage":null,"size":39,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":5,"open_issues":1,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openbmc/openbmc-tools/pulls/4"},"html":{"href":"https://github.com/openbmc/openbmc-tools/pull/4"},"issue":{"href":"https://api.github.com/repos/openbmc/openbmc-tools/issues/4"},"comments":{"href":"https://api.github.com/repos/openbmc/openbmc-tools/issues/4/comments"},"review_comments":{"href":"https://api.github.com/repos/openbmc/openbmc-tools/pulls/4/comments"},"review_comment":{"href":"https://api.github.com/repos/openbmc/openbmc-tools/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/openbmc/openbmc-tools/pulls/4/commits"},"statuses":{"href":"https://api.github.com/repos/openbmc/openbmc-tools/statuses/f9aee3e5bb90c854eb6ac48426caee098ecd3b7c"}},"author_association":"NONE"}}
{"actor":{"display_login":"amboar"}}