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))
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)