def _do_request(self, method, action, body=None,
                    headers=None, vsm_ip=None):
        """Perform the HTTP request.

        The response is in either JSON format or plain text. A GET method will
        invoke a JSON response while a PUT/POST/DELETE returns message from the
        VSM in plain text format.
        Exception is raised when VSM replies with an INTERNAL SERVER ERROR HTTP
        status code (500) i.e. an error has occurred on the VSM or SERVICE
        UNAVAILABLE (404) i.e. VSM is not reachable.

        :param method: type of the HTTP request. POST, GET, PUT or DELETE
        :param action: path to which the client makes request
        :param body: dict for arguments which are sent as part of the request
        :param headers: header for the HTTP request
        :param vsm_ip: vsm_ip for the HTTP request. If not provided then
                       request will be sent to all VSMs.
        :returns: JSON or plain text in HTTP response
        """

        action = self.action_prefix + action
        if body:
            body = jsonutils.dumps(body)
            LOG.debug("req: %s", body)
        hosts = []
        if vsm_ip:
            hosts.append(vsm_ip)
        else:
            hosts = self.vsm_ips
        if not headers:
            headers = self._get_auth_header()
            headers['Content-Type'] = headers['Accept'] = "application/json"
        for vsm_ip in hosts:
            if netaddr.valid_ipv6(vsm_ip):
                # Enclose IPv6 address in [] in the URL
                vsm_action = action % ("[%s]" % vsm_ip)
            else:
                # IPv4 address
                vsm_action = action % vsm_ip
            for attempt in range(self.max_vsm_retries + 1):
                try:
                    LOG.debug("[VSM %(vsm)s attempt %(id)s]: Connecting.." %
                        {"vsm": vsm_ip, "id": attempt})
                    resp = self.pool.spawn(requests.request,
                                           method,
                                           url=vsm_action,
                                           data=body,
                                           headers=headers,
                                           timeout=self.timeout).wait()
                    break
                except Exception as e:
                    LOG.debug("[VSM %(vsm)s attempt %(id)s]: Conn timeout." %
                        {"vsm": vsm_ip, "id": attempt})
                    if attempt == self.max_vsm_retries:
                        LOG.error(_LE("VSM %s, Conn failed."), vsm_ip)
                        raise n1kv_exc.VSMConnectionFailed(reason=e)
            if resp.status_code != requests.codes.OK:
                LOG.error(_LE("VSM %(vsm)s, Got error: %(err)s"),
                    {"vsm": vsm_ip, "err": resp.text})
                raise n1kv_exc.VSMError(reason=resp.text)
        if 'application/json' in resp.headers['content-type']:
            try:
                return resp.json()
            except __HOLE__:
                return {}
        elif 'text/plain' in resp.headers['content-type']:
            LOG.info(_LI("VSM: %s"), resp.text)
dataset/ETHPy150Open openstack/networking-cisco/networking_cisco/plugins/ml2/drivers/cisco/n1kv/n1kv_client.py/Client._do_request