code: func (gce *Cloud) GetAllZones() (sets.String, error) {
  	// Fast-path for non-multizone
  	if len(gce.managedZones) == 1 {
  		return sets.NewString(gce.managedZones...), nil
  	}
  
  	// TODO: Caching, but this is currently only called when we are creating a volume,
  	// which is a relatively infrequent operation, and this is only # zones API calls
  	zones := sets.NewString()
  
  	// TODO: Parallelize, although O(zones) so not too bad (N <= 3 typically)
  	for _, zone := range gce.managedZones {
  		// We only retrieve one page in each zone - we only care about existence
  		listCall := gce.service.Instances.List(gce.projectID, zone)
  
  		// No filter: We assume that a zone is either used or unused
  		// We could only consider running nodes (like we do in List above),
  		// but probably if instances are starting we still want to consider them.
  		// I think we should wait until we have a reason to make the
  		// call one way or the other; we generally can't guarantee correct
  		// volume spreading if the set of zones is changing
  		// (and volume spreading is currently only a heuristic).
  		// Long term we want to replace GetAllZones (which primarily supports volume
  		// spreading) with a scheduler policy that is able to see the global state of
  		// volumes and the health of zones.
  
  		// Just a minimal set of fields - we only care about existence
  		listCall = listCall.Fields("items(name)")
  
  		res, err := listCall.Do()
  		if err != nil {
  			return nil, err
  		}
  		if len(res.Items) != 0 {
  			zones.Insert(zone)
  		}
  	}
  
  	return zones, nil
  }
docs: // GetAllZones returns all the zones in which nodes are running