@oauth_decorator.oauth_required
  @data_handler.data_required
  def get_instances(self):
    """List instances.

    Uses app engine app identity to retrieve an access token for the app
    engine service account. No client OAuth required. External IP is used
    to determine if the instance is actually running.
    """

    gce_project = self._create_gce()
    instances = gce_appengine.GceAppEngine().run_gce_request(
        self,
        gce_project.list_instances,
        'Error listing instances: ',
        filter='name eq ^%s-.*' % self.instance_prefix())

    # A map of instanceName -> (ip, RPC)
    health_rpcs = {}

    # Convert instance info to dict and check server status.
    num_running = 0
    instance_dict = {}
    if instances:
      for instance in instances:
        instance_record = {}
        instance_dict[instance.name] = instance_record
        if instance.status:
          instance_record['status'] = instance.status
        else:
          instance_record['status'] = 'OTHER'
        ip = None
        for interface in instance.network_interfaces:
          for config in interface.get('accessConfigs', []):
            if 'natIP' in config:
              ip = config['natIP']
              instance_record['externalIp'] = ip
              break
          if ip: break

        # Ping the instance server. Grab stats from /debug/vars.
        if ip and instance.status == 'RUNNING':
          num_running += 1
          health_url = 'http://%s/debug/vars?t=%d' % (ip, int(time.time()))
          logging.debug('Health checking %s', health_url)
          rpc = urlfetch.create_rpc(deadline = HEALTH_CHECK_TIMEOUT)
          urlfetch.make_fetch_call(rpc, url=health_url)
          health_rpcs[instance.name] = rpc

    # Ping through a LBs too.  Only if we get success there do we know we are
    # really serving.
    loadbalancers = []
    lb_rpcs = {}
    if instances and len(instances) > 1:
      loadbalancers = self._get_lb_servers()
    if num_running > 0 and loadbalancers:
      for lb in loadbalancers:
        health_url = 'http://%s/health?t=%d' % (lb, int(time.time()))
        logging.debug('Health checking %s', health_url)
        rpc = urlfetch.create_rpc(deadline = HEALTH_CHECK_TIMEOUT)
        urlfetch.make_fetch_call(rpc, url=health_url)
        lb_rpcs[lb] = rpc

    # wait for RPCs to complete and update dict as necessary
    vars_aggregator = ServerVarsAggregator()

    # TODO: there is significant duplication here.  Refactor.
    for (instance_name, rpc) in health_rpcs.items():
      result = None
      instance_record = instance_dict[instance_name]
      try:
        result = rpc.get_result()
        if result and "memstats" in result.content:
          logging.debug('%s healthy!', instance_name)
          instance_record['status'] = 'SERVING'
          instance_vars = {}
          try:
            instance_vars = json.loads(result.content)
            instance_record['vars'] = instance_vars
            vars_aggregator.aggregate_vars(instance_vars)
          except ValueError as error:
            logging.error('Error decoding vars json for %s: %s', instance_name, error)
        else:
          logging.debug('%s unhealthy. Content: %s', instance_name, result.content)
      except urlfetch.Error as error:
        logging.debug('%s unhealthy: %s', instance_name, str(error))

    # Check health status through the load balancer.
    loadbalancer_healthy = bool(lb_rpcs)
    for (lb, lb_rpc) in lb_rpcs.items():
      result = None
      try:
        result = lb_rpc.get_result()
        if result and result.content in "ok":
          logging.info('LB %s healthy: %s\n%s', lb, result.headers, result.content)
        else:
          logging.info('LB %s result not okay: %s, %s', lb, result.status_code, result.content)
          loadbalancer_healthy = False
          break
      except urlfetch.Error as error:
        logging.info('LB %s fetch error: %s', lb, str(error))
        loadbalancer_healthy = False
        break

    response_dict = {
      'instances': instance_dict,
      'vars': vars_aggregator.get_aggregate(),
      'loadbalancers': loadbalancers,
      'loadbalancer_healthy': loadbalancer_healthy,
    }
    self.response.headers['Content-Type'] = 'application/json'
    self.response.out.write(json.dumps(response_dict))
dataset/ETHPy150Open googlearchive/compute-appengine-demo-suite-python/demo-suite/demos/fractal/main.py/Fractal.get_instances/swapped operands of `in`