func (e *NetworkController) updateLoadBalancer(service *api.Service, lb *networkprovider.LoadBalancer) (*api.LoadBalancerStatus, error) { loadBalancerFullName := networkprovider.BuildLoadBalancerName(service.Name, service.Namespace) newHosts, _ := e.getEndpointHosts(service) if len(newHosts) == 0 { glog.V(4).Infof("NetworkController: no endpoints on service %s", service.Name) return nil, nil } if e.hostPortsEqual(lb.Hosts, newHosts) { return nil, nil } vip, err := e.netProvider.LoadBalancers().UpdateLoadBalancer(loadBalancerFullName, newHosts, service.Spec.ExternalIPs) if err != nil { glog.Errorf("NetworkController: couldn't update loadlbalancer %s:%v", loadBalancerFullName, err) return nil, err } glog.V(4).Infof("NetworkController: loadbalancer %s (vip: %s) updated", loadBalancerFullName, vip) status := &api.LoadBalancerStatus{} status.Ingress = []api.LoadBalancerIngress{{IP: vip}} return status, nil }
func (e *NetworkController) createLoadBalancer(service *api.Service) (*api.LoadBalancerStatus, error) { newHosts, _ := e.getEndpointHosts(service) if len(newHosts) == 0 { glog.V(4).Infof("NetworkController: no endpoints on service %s", service.Name) return nil, nil } // get namespace of svc namespace, err := e.client.Namespaces().Get(service.Namespace) if err != nil { glog.Errorf("NetworkController: couldn't get namespace for service %s: %v", service.Name, err) return nil, err } if namespace.Spec.Network == "" { glog.Warningf("NetworkController: there is no network associated with namespace %s", namespace.Name) return nil, nil } // get network of namespace network, err := e.client.Networks().Get(namespace.Spec.Network) if err != nil { glog.Errorf("NetworkController: couldn't get network for namespace %s: %v", namespace.Name, err) return nil, err } var networkInfo *networkprovider.Network if network.Spec.ProviderNetworkID != "" { networkInfo, err = e.netProvider.Networks().GetNetworkByID(network.Spec.ProviderNetworkID) } else { networkName := networkprovider.BuildNetworkName(network.Name, network.Tenant) networkInfo, err = e.netProvider.Networks().GetNetwork(networkName) } if err != nil { glog.Errorf("NetworkController: couldn't get network from networkprovider: %v", err) return nil, err } // create loadbalancer for service loadBalancerFullName := networkprovider.BuildLoadBalancerName(service.Name, service.Namespace) providerLoadBalancer := networkprovider.LoadBalancer{ Name: loadBalancerFullName, // TODO: support more loadbalancer type Type: networkprovider.LoadBalancerTypeTCP, TenantID: networkInfo.TenantID, Subnets: networkInfo.Subnets, Hosts: newHosts, ExternalIPs: service.Spec.ExternalIPs, } vip, err := e.netProvider.LoadBalancers().CreateLoadBalancer(&providerLoadBalancer, service.Spec.SessionAffinity) if err != nil { glog.Errorf("NetworkController: create load balancer %s failed: %v", loadBalancerFullName, err) return nil, err } glog.V(4).Infof("NetworkController: load balancer for service %s created", service.Name) status := &api.LoadBalancerStatus{} status.Ingress = []api.LoadBalancerIngress{{IP: vip}} return status, nil }
func (e *NetworkController) syncService(key string) { glog.V(4).Infof("NetworkController: processing service %v", key) obj, exists, err := e.serviceStore.Store.GetByKey(key) if err != nil || !exists { // Delete the corresponding loadbalancer, as the service has been deleted. namespace, name, err := cache.SplitMetaNamespaceKey(key) if err != nil { glog.Errorf("NetworkController: couldn't understand the key %s: %v", key, err) return } loadBalancerFullName := networkprovider.BuildLoadBalancerName(name, namespace) deleteError := e.netProvider.LoadBalancers().DeleteLoadBalancer(loadBalancerFullName) if deleteError != nil { glog.Errorf("NetworkController: delete loadbalancer %s failed: %v", loadBalancerFullName, err) } return } service := obj.(*api.Service) if service.Spec.Selector == nil { // services without a selector receive no endpoints from this controller; // these services will receive the endpoints that are created out-of-band via the REST API. return } // check if loadbalancer already created loadBalanerShouldExist := !(len(service.Spec.ExternalIPs) == 0) var status *api.LoadBalancerStatus loadBalancerFullName := networkprovider.BuildLoadBalancerName(service.Name, service.Namespace) loadBalancer, err := e.netProvider.LoadBalancers().GetLoadBalancer(loadBalancerFullName) if err != nil && err.Error() == networkprovider.ErrNotFound.Error() { if loadBalanerShouldExist { // create new loadbalancer status, _ = e.createLoadBalancer(service) } } else if err != nil { glog.Errorf("NetworkController: couldn't get loadbalancer from networkprovider: %v", err) return } else { if loadBalanerShouldExist { // update loadbalancer status, _ = e.updateLoadBalancer(service, loadBalancer) } else { // delete loadbalancer deleteError := e.netProvider.LoadBalancers().DeleteLoadBalancer(loadBalancerFullName) if deleteError != nil { glog.Errorf("NetworkController: delete loadbalancer %s failed: %v", loadBalancerFullName, err) } } } if status != nil { service.Status.LoadBalancer = *status err := e.updateService(service) if err != nil { e.eventRecorder.Event(service, "created loadbalancer", "created loadbalancer") } } }