package plugin import ( "fmt" "net" log "github.com/golang/glog" osclient "github.com/openshift/origin/pkg/client" osconfigapi "github.com/openshift/origin/pkg/cmd/server/api" osapi "github.com/openshift/origin/pkg/sdn/api" "github.com/openshift/origin/pkg/util/netutils" kapi "k8s.io/kubernetes/pkg/api" kapiunversioned "k8s.io/kubernetes/pkg/api/unversioned" kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" kerrors "k8s.io/kubernetes/pkg/util/errors" ) type OsdnMaster struct { kClient *kclientset.Clientset osClient *osclient.Client networkInfo *NetworkInfo subnetAllocator *netutils.SubnetAllocator vnids *masterVNIDMap } func StartMaster(networkConfig osconfigapi.MasterNetworkConfig, osClient *osclient.Client, kClient *kclientset.Clientset) error { if !osapi.IsOpenShiftNetworkPlugin(networkConfig.NetworkPluginName) { return nil } log.Infof("Initializing SDN master of type %q", networkConfig.NetworkPluginName) master := &OsdnMaster{ kClient: kClient, osClient: osClient, } var err error master.networkInfo, err = parseNetworkInfo(networkConfig.ClusterNetworkCIDR, networkConfig.ServiceNetworkCIDR) if err != nil { return err } createConfig := false updateConfig := false cn, err := master.osClient.ClusterNetwork().Get(osapi.ClusterNetworkDefault) if err == nil { if master.networkInfo.ClusterNetwork.String() != cn.Network || networkConfig.HostSubnetLength != cn.HostSubnetLength || master.networkInfo.ServiceNetwork.String() != cn.ServiceNetwork || networkConfig.NetworkPluginName != cn.PluginName { updateConfig = true } } else { cn = &osapi.ClusterNetwork{ TypeMeta: kapiunversioned.TypeMeta{Kind: "ClusterNetwork"}, ObjectMeta: kapi.ObjectMeta{Name: osapi.ClusterNetworkDefault}, } createConfig = true } if createConfig || updateConfig { if err = master.validateNetworkConfig(); err != nil { return err } size, len := master.networkInfo.ClusterNetwork.Mask.Size() if networkConfig.HostSubnetLength < 1 || networkConfig.HostSubnetLength >= uint32(len-size) { return fmt.Errorf("invalid HostSubnetLength %d for network %s (must be from 1 to %d)", networkConfig.HostSubnetLength, networkConfig.ClusterNetworkCIDR, len-size) } cn.Network = master.networkInfo.ClusterNetwork.String() cn.HostSubnetLength = networkConfig.HostSubnetLength cn.ServiceNetwork = master.networkInfo.ServiceNetwork.String() cn.PluginName = networkConfig.NetworkPluginName } if createConfig { cn, err := master.osClient.ClusterNetwork().Create(cn) if err != nil { return err } log.Infof("Created ClusterNetwork %s", clusterNetworkToString(cn)) } else if updateConfig { cn, err := master.osClient.ClusterNetwork().Update(cn) if err != nil { return err } log.Infof("Updated ClusterNetwork %s", clusterNetworkToString(cn)) } if err = master.SubnetStartMaster(master.networkInfo.ClusterNetwork, networkConfig.HostSubnetLength); err != nil { return err } if osapi.IsOpenShiftMultitenantNetworkPlugin(networkConfig.NetworkPluginName) { master.vnids = newMasterVNIDMap() if err = master.VnidStartMaster(); err != nil { return err } } return nil } func (master *OsdnMaster) validateNetworkConfig() error { hostIPNets, _, err := netutils.GetHostIPNetworks([]string{TUN}) if err != nil { return err } ni := master.networkInfo errList := []error{} // Ensure cluster and service network don't overlap with host networks for _, ipNet := range hostIPNets { if ipNet.Contains(ni.ClusterNetwork.IP) { errList = append(errList, fmt.Errorf("Error: Cluster IP: %s conflicts with host network: %s", ni.ClusterNetwork.IP.String(), ipNet.String())) } if ni.ClusterNetwork.Contains(ipNet.IP) { errList = append(errList, fmt.Errorf("Error: Host network with IP: %s conflicts with cluster network: %s", ipNet.IP.String(), ni.ClusterNetwork.String())) } if ipNet.Contains(ni.ServiceNetwork.IP) { errList = append(errList, fmt.Errorf("Error: Service IP: %s conflicts with host network: %s", ni.ServiceNetwork.String(), ipNet.String())) } if ni.ServiceNetwork.Contains(ipNet.IP) { errList = append(errList, fmt.Errorf("Error: Host network with IP: %s conflicts with service network: %s", ipNet.IP.String(), ni.ServiceNetwork.String())) } } // Ensure each host subnet is within the cluster network subnets, err := master.osClient.HostSubnets().List(kapi.ListOptions{}) if err != nil { return fmt.Errorf("Error in initializing/fetching subnets: %v", err) } for _, sub := range subnets.Items { subnetIP, _, _ := net.ParseCIDR(sub.Subnet) if subnetIP == nil { errList = append(errList, fmt.Errorf("Failed to parse network address: %s", sub.Subnet)) continue } if !ni.ClusterNetwork.Contains(subnetIP) { errList = append(errList, fmt.Errorf("Error: Existing node subnet: %s is not part of cluster network: %s", sub.Subnet, ni.ClusterNetwork.String())) } } // Ensure each service is within the services network services, err := master.kClient.Core().Services(kapi.NamespaceAll).List(kapi.ListOptions{}) if err != nil { return err } for _, svc := range services.Items { if !ni.ServiceNetwork.Contains(net.ParseIP(svc.Spec.ClusterIP)) { errList = append(errList, fmt.Errorf("Error: Existing service with IP: %s is not part of service network: %s", svc.Spec.ClusterIP, ni.ServiceNetwork.String())) } } return kerrors.NewAggregate(errList) }