示例#1
0
 def _check_cluster_id(self, response):
     cluster_id = response.getheader("x-etcd-cluster-id")
     if not cluster_id:
         _log.warning("etcd response did not contain a cluster ID")
         return
     id_changed = (self.expected_cluster_id
                   and cluster_id != self.expected_cluster_id)
     # Update the ID so we only raise the exception once.
     old_expected_cluster_id = self.expected_cluster_id
     self.expected_cluster_id = cluster_id
     if id_changed:
         # Defensive: clear the pool so that we connect afresh next
         # time.
         self.http.clear()
         raise etcd.EtcdClusterIdChanged(
             'The UUID of the cluster changed from {} to '
             '{}.'.format(old_expected_cluster_id, cluster_id))
示例#2
0
    def api_execute(self, path, method, params=None, timeout=None):
        """ Executes the query. """

        some_request_failed = False
        response = False

        if timeout is None:
            timeout = self.read_timeout

        if timeout == 0:
            timeout = None

        if not path.startswith('/'):
            raise ValueError('Path does not start with /')

        while not response:
            try:
                url = self._base_uri + path

                if (method == self._MGET) or (method == self._MDELETE):
                    response = self.http.request(method,
                                                 url,
                                                 timeout=timeout,
                                                 fields=params,
                                                 redirect=self.allow_redirect,
                                                 preload_content=False)

                elif (method == self._MPUT) or (method == self._MPOST):
                    response = self.http.request_encode_body(
                        method,
                        url,
                        fields=params,
                        timeout=timeout,
                        encode_multipart=False,
                        redirect=self.allow_redirect,
                        preload_content=False)
                else:
                    raise etcd.EtcdException(
                        'HTTP method {} not supported'.format(method))

            # urllib3 doesn't wrap all httplib exceptions and earlier versions
            # don't wrap socket errors either.
            except (urllib3.exceptions.HTTPError, HTTPException,
                    socket.error) as e:
                _log.error("Request to server %s failed: %r", self._base_uri,
                           e)
                if self._allow_reconnect:
                    _log.info("Reconnection allowed, looking for another "
                              "server.")
                    # _next_server() raises EtcdException if there are no
                    # machines left to try, breaking out of the loop.
                    self._base_uri = self._next_server()
                    some_request_failed = True
                else:
                    _log.debug("Reconnection disabled, giving up.")
                    raise etcd.EtcdConnectionFailed(
                        "Connection to etcd failed due to %r" % e)
            except:
                _log.exception("Unexpected request failure, re-raising.")
                raise

            else:
                # Check the cluster ID hasn't changed under us.  We use
                # preload_content=False above so we can read the headers
                # before we wait for the content of a long poll.
                cluster_id = response.getheader("x-etcd-cluster-id")
                id_changed = (self.expected_cluster_id
                              and cluster_id is not None
                              and cluster_id != self.expected_cluster_id)
                # Update the ID so we only raise the exception once.
                old_expected_cluster_id = self.expected_cluster_id
                self.expected_cluster_id = cluster_id
                if id_changed:
                    # Defensive: clear the pool so that we connect afresh next
                    # time.
                    self.http.clear()
                    raise etcd.EtcdClusterIdChanged(
                        'The UUID of the cluster changed from {} to '
                        '{}.'.format(old_expected_cluster_id, cluster_id))

        if some_request_failed:
            if not self._use_proxies:
                # The cluster may have changed since last invocation
                self._machines_cache = self.machines
            self._machines_cache.remove(self._base_uri)
        return self._handle_server_response(response)