Add Replace certificate command

Redfish does not support certificate delete rather supports
certificate replace added support for certificate replace.

Tested:
-------OP930-------
$ python openbmctool.py -H $BMC_IP -U root -P 0penBmc certificate replace
server https -f cert.pem
Attempting login...
Replace complete.
{
  "data": null,
  "message": "200 OK",
  "status": "ok"
}
User root has been logged out

-------OP940-------
bash-4.2$ python openbmctool.py -H $BMC_IP -U xxxx -P xxxx certificate --help
usage: openbmctool.py certificate [-h] {update,replace} ...

optional arguments:
  -h, --help        show this help message and exit

subcommands:
  valid certificate commands

  {update,replace}  sub-command help
    update          Update the certificate
    replace         Replace the certificate
bash-4.2$ python openbmctool.py -H abc -U xxxx -P xxxx certificate replace --help
usage: openbmctool.py certificate replace [-h] -f FILELOC
                                          {server,client,authority}

positional arguments:
  {server,client,authority}
                        certificate type to replace

optional arguments:
  -h, --help            show this help message and exit
  -f FILELOC, --fileloc FILELOC
                        The absolute path to the certificate file

bash-4.2$ python openbmctool.py -H $BMC_IP -U xxxx -P xxxx certificate replace server -f cert.pem
Attempting login...
Replacing certificate url=/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1
Replace complete.
{
  "@odata.context": "/redfish/v1/$metadata#Certificate.Certificate",
  "@odata.id": "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1",
  "@odata.type": "#Certificate.v1_0_0.Certificate",
  "CertificateString": "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n",
  "Description": "HTTPS certificate",
  "Id": "1",
  "Issuer": {
    "CommonName": "localhost",
    "Organization": "openbmc-project.xyz"
  },
  "KeyUsage": [],
  "Name": "HTTPS certificate",
  "Subject": {
    "CommonName": "localhost",
    "Organization": "openbmc-project.xyz"
  },
  "ValidNotAfter": "2029-05-09T19:59:40+00:00",
  "ValidNotBefore": "2019-05-12T19:59:40+00:00"
}

Signed-off-by: Marri Devender Rao <devenrao@in.ibm.com>
Change-Id: I4d222a3db1590c2c4206798ac3cc0eea4899eb48
diff --git a/thalerj/openbmctool.py b/thalerj/openbmctool.py
index 686796b..d06a38e 100755
--- a/thalerj/openbmctool.py
+++ b/thalerj/openbmctool.py
@@ -2598,6 +2598,54 @@
     else:
         print("Delete complete.")
 
+def certificateReplace(host, args, session):
+    """
+         Called by certificate management function. replace server/client/
+         authority certificates
+         Example:
+         certificate replace server https -f cert.pem
+         certificate replace authority ldap -f Root-CA.pem
+         certificate replace client ldap -f cert.pem
+         @param host: string, the hostname or IP address of the bmc
+         @param args: contains additional arguments used by the certificate
+                      replace sub command
+         @param session: the active session to use
+    """
+    cert = open(args.fileloc, 'rb').read()
+    try:
+        if redfishSupportPresent(host, session):
+            httpHeader = {'Content-Type': 'application/json'}
+            httpHeader.update(xAuthHeader)
+            url = "";
+            if(args.type.lower() == 'server'):
+                url = "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
+            elif(args.type.lower() == 'client'):
+                url = "/redfish/v1/AccountService/LDAP/Certificates/1"
+            elif(args.type.lower() == 'authority'):
+                url = "/redfish/v1/Managers/bmc/Truststore/Certificates/1"
+            replaceUrl = "https://" + host + \
+                "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"
+            data ={"CertificateUri":{"@odata.id":url}, "CertificateType":"PEM",
+                    "CertificateString":cert}
+            resp = session.post(replaceUrl, headers=httpHeader, json=data, verify=False)
+        else:
+            httpHeader = {'Content-Type': 'application/octet-stream'}
+            httpHeader.update(xAuthHeader)
+            url = "https://" + host + "/xyz/openbmc_project/certs/" + \
+                args.type.lower() + "/" + args.service.lower()
+            resp = session.delete(url, headers=httpHeader)
+            resp = session.put(url, headers=httpHeader, data=cert, verify=False)
+    except(requests.exceptions.Timeout):
+        return(connectionErrHandler(args.json, "Timeout", None))
+    except(requests.exceptions.ConnectionError) as err:
+        return connectionErrHandler(args.json, "ConnectionError", err)
+    if resp.status_code != 200:
+        print(resp.text)
+        return "Failed to replace the certificate"
+    else:
+        print("Replace complete.")
+    return resp.text
+
 def enableLDAP(host, args, session):
     """
          Called by the ldap function. Configures LDAP.
@@ -3922,6 +3970,16 @@
     certDelete.add_argument('service', choices=['https', 'ldap'], help="Service to delete the certificate")
     certDelete.set_defaults(func=certificateDelete)
 
+    certReplace = certMgmt_subproc.add_parser('replace',
+        help="Replace the certificate")
+    certReplace.add_argument('type', choices=['server', 'client', 'authority'],
+        help="certificate type to replace")
+    certReplace.add_argument('service', choices=['https', 'ldap'],
+        help="Service to replace the certificate")
+    certReplace.add_argument('-f', '--fileloc', required=True,
+        help="The absolute path to the certificate file")
+    certReplace.set_defaults(func=certificateReplace)
+
     # local users
     parser_users = subparsers.add_parser("local_users", help="Work with local users")
     parser_users.add_argument('local_users', choices=['disableall','enableall', 'queryenabled'], help="Disable, enable or query local user accounts")