// reconcileExternalServices updates balancers for external services, so that they will match the nodes given.
// Returns true if something went wrong and we should call reconcile again.
func (nc *NodeController) reconcileExternalServices(nodes *api.NodeList) (shouldRetry bool) {
	balancer, ok := nc.cloud.TCPLoadBalancer()
	if !ok {
		glog.Error("The cloud provider does not support external TCP load balancers.")
		return false
	}

	zones, ok := nc.cloud.Zones()
	if !ok {
		glog.Error("The cloud provider does not support zone enumeration.")
		return false
	}
	zone, err := zones.GetZone()
	if err != nil {
		glog.Errorf("Error while getting zone: %v", err)
		return false
	}

	hosts := []string{}
	for _, node := range nodes.Items {
		hosts = append(hosts, node.Name)
	}

	services, err := nc.kubeClient.Services(api.NamespaceAll).List(labels.Everything())
	if err != nil {
		glog.Errorf("Error while listing services: %v", err)
		return true
	}
	shouldRetry = false
	for _, service := range services.Items {
		if service.Spec.CreateExternalLoadBalancer {
			nonTCPPort := false
			for i := range service.Spec.Ports {
				if service.Spec.Ports[i].Protocol != api.ProtocolTCP {
					nonTCPPort = true
					break
				}
			}
			if nonTCPPort {
				// TODO: Support UDP here.
				glog.Errorf("External load balancers for non TCP services are not currently supported: %v.", service)
				continue
			}
			name := cloudprovider.GetLoadBalancerName(&service)
			err := balancer.UpdateTCPLoadBalancer(name, zone.Region, hosts)
			if err != nil {
				glog.Errorf("External error while updating TCP load balancer: %v.", err)
				shouldRetry = true
			}
		}
	}
	return shouldRetry
}
// Updates the external load balancer of a service, assuming we hold the mutex
// associated with the service.
func (s *ServiceController) lockedUpdateLoadBalancerHosts(service *api.Service, hosts []string) error {
	if !wantsExternalLoadBalancer(service) {
		return nil
	}

	name := cloudprovider.GetLoadBalancerName(service)
	err := s.balancer.UpdateTCPLoadBalancer(name, s.zone.Region, hosts)
	if err == nil {
		return nil
	}

	// It's only an actual error if the load balancer still exists.
	if _, exists, err := s.balancer.GetTCPLoadBalancer(name, s.zone.Region); err != nil {
		glog.Errorf("External error while checking if TCP load balancer %q exists: name, %v")
	} else if !exists {
		return nil
	}
	return err
}
func (s *ServiceController) loadBalancerName(service *api.Service) string {
	return cloudprovider.GetLoadBalancerName(service)
}