docs: def post(self, uri, body=None, logon_required=True,
               wait_for_completion=False, operation_timeout=None):
          """
          Perform the HTTP POST method against the resource identified by a URI,
          using a provided request body.
  
          A set of standard HTTP headers is automatically part of the request.
  
          HMC operations using HTTP POST are either synchronous or asynchronous.
          Asynchronous operations return the URI of an asynchronously executing
          job that can be queried for status and result.
  
          Examples for synchronous operations:
  
          * With no result: "Logon", "Update CPC Properties"
          * With a result: "Create Partition"
  
          Examples for asynchronous operations:
  
          * With no result: "Start Partition"
  
          The `wait_for_completion` parameter of this method can be used to deal
          with asynchronous HMC operations in a synchronous way.
  
          If executing the operation reveals that the HMC session token is
          expired, this method re-logs on and retries the operation.
  
          The timeout and retry
  
          Parameters:
  
            uri (:term:`string`):
              Relative URI path of the resource, e.g. "/api/session".
              This URI is relative to the base URL of the session (see the
              :attr:`~zhmcclient.Session.base_url` property).
              Must not be `None`.
  
            body (:term:`json object`):
              JSON object to be used as the HTTP request body (payload).
              `None` means the same as an empty dictionary, namely that no HTTP
              body is included in the request.
  
            logon_required (bool):
              Boolean indicating whether the operation requires that the session
              is logged on to the HMC. For example, the "Logon" operation does
              not require that.
  
            wait_for_completion (bool):
              Boolean controlling whether this method should wait for completion
              of the requested asynchronous HMC operation.
  
              A value of `True` will cause an additional entry in the time
              statistics to be created that represents the entire asynchronous
              operation including the waiting for its completion.
              That time statistics entry will have a URI that is the targeted
              URI, appended with "+completion".
  
              For synchronous HMC operations, this parameter has no effect on
              the operation execution or on the return value of this method, but
              it should still be set (or defaulted) to `False` in order to avoid
              the additional entry in the time statistics.
  
            operation_timeout (:term:`number`):
              Timeout in seconds, when waiting for completion of an asynchronous
              operation. The special value 0 means that no timeout is set. `None`
              means that the default async operation timeout of the session is
              used.
  
              For `wait_for_completion=True`, a
              :exc:`~zhmcclient.OperationTimeout` is raised when the timeout
              expires.
  
              For `wait_for_completion=False`, this parameter has no effect.
  
          Returns:
  
            : A :term:`json object` or `None` or a :class:`~zhmcclient.Job`
            object, as follows:
  
            * For synchronous HMC operations, and for asynchronous HMC
              operations with `wait_for_completion=True`:
  
              If this method returns, the HMC operation has completed
              successfully (otherwise, an exception is raised).
              For asynchronous HMC operations, the associated job has been
              deleted.
  
              The return value is the result of the HMC operation as a
              :term:`json object`, or `None` if the operation has no result.
              See the section in the :term:`HMC API` book about the specific
              HMC operation for a description of the members of the returned
              JSON object.
  
            * For asynchronous HMC operations with `wait_for_completion=False`:
  
              If this method returns, the asynchronous execution of the HMC
              operation has been started successfully as a job on the HMC (if
              the operation could not be started, an exception is raised).
  
              The return value is a :class:`~zhmcclient.Job` object
              representing the job on the HMC.
  
          Raises:
  
            :exc:`~zhmcclient.HTTPError`
            :exc:`~zhmcclient.ParseError`
            :exc:`~zhmcclient.ClientAuthError`
            :exc:`~zhmcclient.ServerAuthError`
            :exc:`~zhmcclient.ConnectionError`
            :exc:`~zhmcclient.OperationTimeout`: The timeout expired while
              waiting for completion of the asynchronous operation.
            :exc:`TypeError`: Body has invalid type.
          """
          if logon_required:
              self.logon()
          url = self.base_url + uri
          headers = self.headers.copy()  # Standard headers
  
          if body is None:
              data = None
          elif isinstance(body, dict):
              data = json.dumps(body)
              # Content-type is already set in standard headers.
          elif isinstance(body, six.text_type):
              data = body.encode('utf-8')
              headers['Content-type'] = 'application/octet-stream'
          elif isinstance(body, six.binary_type):
              data = body
              headers['Content-type'] = 'application/octet-stream'
          elif isinstance(body, collections.Iterable):
              # For example, open files: open(), io.open()
              data = body
              headers['Content-type'] = 'application/octet-stream'
          else:
              raise TypeError("Body has invalid type: {}".format(type(body)))
  
          self._log_http_request('POST', url, headers=headers, content=data)
          req = self._session or requests
          req_timeout = (self.retry_timeout_config.connect_timeout,
                         self.retry_timeout_config.read_timeout)
          if wait_for_completion:
              stats_total = self.time_stats_keeper.get_stats(
                  'post ' + uri + '+completion')
              stats_total.begin()
          try:
              stats = self.time_stats_keeper.get_stats('post ' + uri)
              stats.begin()
              try:
                  if data is None:
                      result = req.post(url, headers=headers,
                                        verify=False, timeout=req_timeout)
                  else:
                      result = req.post(url, data=data, headers=headers,
                                        verify=False, timeout=req_timeout)
              except requests.exceptions.RequestException as exc:
                  _handle_request_exc(exc, self.retry_timeout_config)
              finally:
                  stats.end()
              self._log_http_response('POST', url,
                                      status=result.status_code,
                                      headers=result.headers,
                                      content=result.content)
  
              if result.status_code in (200, 201):
                  return _result_object(result)
              elif result.status_code == 204:
                  # No content
                  return None
              elif result.status_code == 202:
                  if result.content == '':
                      # Some operations (e.g. "Restart Console",
                      # "Shutdown Console" or "Cancel Job") return 202
                      # with no response content.
                      return None
                  else:
                      # This is the most common case to return 202: An
                      # asynchronous job has been started.
                      result_object = _result_object(result)
                      job_uri = result_object['job-uri']
                      job = Job(self, job_uri, 'POST', uri)
                      if wait_for_completion:
                          return job.wait_for_completion(operation_timeout)
                      else:
                          return job
              elif result.status_code == 403:
                  result_object = _result_object(result)
                  reason = result_object.get('reason', None)
                  if reason == 5:
                      # API session token expired: re-logon and retry
                      self._do_logon()
                      return self.post(uri, body, logon_required)
                  else:
                      msg = result_object.get('message', None)
                      raise ServerAuthError("HTTP authentication failed: {}".
                                            format(msg),
                                            HTTPError(result_object))
              else:
                  result_object = _result_object(result)
                  raise HTTPError(result_object)
          finally:
              if wait_for_completion:
                  stats_total.end()