code: def machines(self):
          
  
          kwargs = self._build_request_parameters()
  
          while True:
              try:
                  response = self.http.request(self._MGET, self._base_uri + self.version_prefix + '/machines', **kwargs)
                  data = self._handle_server_response(response).data.decode('utf-8')
                  machines = [m.strip() for m in data.split(',') if m.strip()]
                  logger.debug("Retrieved list of machines: %s", machines)
                  if not machines:
                      raise etcd.EtcdException
                  random.shuffle(machines)
                  for url in machines:
                      r = urlparse(url)
                      port = r.port or (443 if r.scheme == 'https' else 80)
                      self._dns_resolver.resolve_async(r.hostname, port)
                  return machines
              except Exception as e:
                  # We can't get the list of machines, if one server is in the
                  # machines cache, try on it
                  logger.error("Failed to get list of machines from %s%s: %r", self._base_uri, self.version_prefix, e)
                  if self._machines_cache:
                      self._base_uri = self._machines_cache.pop(0)
                      logger.info("Retrying on %s", self._base_uri)
                  elif self._update_machines_cache:
                      raise etcd.EtcdException("Could not get the list of servers, "
                                               "maybe you provided the wrong "
                                               "host(s) to connect to?")
                  else:
                      return []
docs: Original `machines` method(property) of `etcd.Client` class raise exception
          when it failed to get list of etcd cluster members. This method is being called
          only when request failed on one of the etcd members during `api_execute` call.
          For us it's more important to execute original request rather then get new topology
          of etcd cluster. So we will catch this exception and return empty list of machines.
          Later, during next `api_execute` call we will forcefully update machines_cache.
  
          Also this method implements the same timeout-retry logic as `api_execute`, because
          the original method was retrying 2 times with the `read_timeout` on each node.