// InitPlugins initializes each plugin. All plugins must have unique names. // This must be called exactly once before any New* methods are called on any // plugins. func (pm *VolumePluginMgr) InitPlugins(plugins []VolumePlugin, host VolumeHost) error { pm.mutex.Lock() defer pm.mutex.Unlock() if pm.plugins == nil { pm.plugins = map[string]VolumePlugin{} } allErrs := []error{} for _, plugin := range plugins { name := plugin.Name() if !validation.IsQualifiedName(name) { allErrs = append(allErrs, fmt.Errorf("volume plugin has invalid name: %#v", plugin)) continue } if _, found := pm.plugins[name]; found { allErrs = append(allErrs, fmt.Errorf("volume plugin %q was registered more than once", name)) continue } plugin.Init(host) pm.plugins[name] = plugin glog.V(1).Infof("Loaded volume plugin %q", name) } return utilerrors.NewAggregate(allErrs) }
// ValidateLabelName validates that the label name is correctly defined. func ValidateLabelName(labelName string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for _, msg := range validation.IsQualifiedName(labelName) { allErrs = append(allErrs, field.Invalid(fldPath, labelName, msg)) } return allErrs }
// InitPlugins initializes each plugin. All plugins must have unique names. // This must be called exactly once before any New* methods are called on any // plugins. func (pm *VolumePluginMgr) InitPlugins(plugins []VolumePlugin, host VolumeHost) error { pm.mutex.Lock() defer pm.mutex.Unlock() if pm.plugins == nil { pm.plugins = map[string]VolumePlugin{} } allErrs := []error{} for _, plugin := range plugins { name := plugin.Name() if errs := validation.IsQualifiedName(name); len(errs) != 0 { allErrs = append(allErrs, fmt.Errorf("volume plugin has invalid name: %q: %s", name, strings.Join(errs, ";"))) continue } if _, found := pm.plugins[name]; found { allErrs = append(allErrs, fmt.Errorf("volume plugin %q was registered more than once", name)) continue } err := plugin.Init(host) if err != nil { glog.Errorf("Failed to load volume plugin %s, error: %s", plugin, err.Error()) allErrs = append(allErrs, err) continue } pm.plugins[name] = plugin glog.V(1).Infof("Loaded volume plugin %q", name) } return utilerrors.NewAggregate(allErrs) }
// ParseTaint parses a taint from a string. Taint must be off the format '<key>=<value>:<effect>'. func ParseTaint(st string) (api.Taint, error) { var taint api.Taint parts := strings.Split(st, "=") if len(parts) != 2 || len(parts[1]) == 0 || len(validation.IsQualifiedName(parts[0])) > 0 { return taint, fmt.Errorf("invalid taint spec: %v", st) } parts2 := strings.Split(parts[1], ":") effect := api.TaintEffect(parts2[1]) errs := validation.IsValidLabelValue(parts2[0]) if len(parts2) != 2 || len(errs) != 0 { return taint, fmt.Errorf("invalid taint spec: %v, %s", st, strings.Join(errs, "; ")) } if effect != api.TaintEffectNoSchedule && effect != api.TaintEffectPreferNoSchedule { return taint, fmt.Errorf("invalid taint spec: %v, unsupported taint effect", st) } taint.Key = parts[0] taint.Value = parts2[0] taint.Effect = effect return taint, nil }
// SlaveAttributesToLabels converts slave attributes into string key/value labels func SlaveAttributesToLabels(attrs []*mesos.Attribute) map[string]string { l := map[string]string{} for _, a := range attrs { if a == nil { continue } var v string k := labelPrefix + a.GetName() switch a.GetType() { case mesos.Value_TEXT: v = a.GetText().GetValue() case mesos.Value_SCALAR: v = strconv.FormatFloat(a.GetScalar().GetValue(), 'G', -1, 64) } if !validation.IsQualifiedName(k) { log.V(3).Infof("ignoring invalid node label name %q", k) continue } if !validation.IsValidLabelValue(v) { log.V(3).Infof("ignoring invalid node label %s value: %q", k, v) continue } l[k] = v } return l }
func parseTaints(spec []string) ([]api.Taint, []api.Taint, error) { var taints, taintsToRemove []api.Taint uniqueTaints := map[api.TaintEffect]sets.String{} for _, taintSpec := range spec { if strings.Index(taintSpec, "=") != -1 && strings.Index(taintSpec, ":") != -1 { parts := strings.Split(taintSpec, "=") if len(parts) != 2 || len(parts[1]) == 0 || len(validation.IsQualifiedName(parts[0])) > 0 { return nil, nil, fmt.Errorf("invalid taint spec: %v", taintSpec) } parts2 := strings.Split(parts[1], ":") errs := validation.IsValidLabelValue(parts2[0]) if len(parts2) != 2 || len(errs) != 0 { return nil, nil, fmt.Errorf("invalid taint spec: %v, %s", taintSpec, strings.Join(errs, "; ")) } if parts2[1] != string(api.TaintEffectNoSchedule) && parts2[1] != string(api.TaintEffectPreferNoSchedule) { return nil, nil, fmt.Errorf("invalid taint spec: %v, unsupported taint effect", taintSpec) } effect := api.TaintEffect(parts2[1]) newTaint := api.Taint{ Key: parts[0], Value: parts2[0], Effect: effect, } // validate if taint is unique by <key, effect> if len(uniqueTaints[newTaint.Effect]) > 0 && uniqueTaints[newTaint.Effect].Has(newTaint.Key) { return nil, nil, fmt.Errorf("duplicated taints with the same key and effect: %v", newTaint) } // add taint to existingTaints for uniqueness check if len(uniqueTaints[newTaint.Effect]) == 0 { uniqueTaints[newTaint.Effect] = sets.String{} } uniqueTaints[newTaint.Effect].Insert(newTaint.Key) taints = append(taints, newTaint) } else if strings.HasSuffix(taintSpec, "-") { taintKey := taintSpec[:len(taintSpec)-1] var effect api.TaintEffect if strings.Index(taintKey, ":") != -1 { parts := strings.Split(taintKey, ":") taintKey = parts[0] effect = api.TaintEffect(parts[1]) } taintsToRemove = append(taintsToRemove, api.Taint{Key: taintKey, Effect: effect}) } else { return nil, nil, fmt.Errorf("unknown taint spec: %v", taintSpec) } } return taints, taintsToRemove, nil }
// validateProvisioner tests if provisioner is a valid qualified name. func validateProvisioner(provisioner string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(provisioner) == 0 { allErrs = append(allErrs, field.Required(fldPath, provisioner)) } if len(provisioner) > 0 { for _, msg := range validation.IsQualifiedName(strings.ToLower(provisioner)) { allErrs = append(allErrs, field.Invalid(fldPath, provisioner, msg)) } } return allErrs }
// Validate compute resource typename. // Refer to docs/design/resources.md for more details. func validateResourceName(value string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for _, msg := range validation.IsQualifiedName(value) { allErrs = append(allErrs, field.Invalid(fldPath, value, msg)) } if len(allErrs) != 0 { return allErrs } if len(strings.Split(value, "/")) == 1 { if !api.IsStandardResourceName(value) { return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource type or fully qualified")) } } return field.ErrorList{} }
// InitNetworkPlugin inits the plugin that matches networkPluginName. Plugins must have unique names. func InitNetworkPlugin(plugins []NetworkPlugin, networkPluginName string, host Host, hairpinMode componentconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) (NetworkPlugin, error) { if networkPluginName == "" { // default to the no_op plugin plug := &NoopNetworkPlugin{} if err := plug.Init(host, hairpinMode, nonMasqueradeCIDR, mtu); err != nil { return nil, err } return plug, nil } pluginMap := map[string]NetworkPlugin{} allErrs := []error{} for _, plugin := range plugins { name := plugin.Name() if errs := validation.IsQualifiedName(name); len(errs) != 0 { allErrs = append(allErrs, fmt.Errorf("network plugin has invalid name: %q: %s", name, strings.Join(errs, ";"))) continue } if _, found := pluginMap[name]; found { allErrs = append(allErrs, fmt.Errorf("network plugin %q was registered more than once", name)) continue } pluginMap[name] = plugin } chosenPlugin := pluginMap[networkPluginName] if chosenPlugin != nil { err := chosenPlugin.Init(host, hairpinMode, nonMasqueradeCIDR, mtu) if err != nil { allErrs = append(allErrs, fmt.Errorf("Network plugin %q failed init: %v", networkPluginName, err)) } else { glog.V(1).Infof("Loaded network plugin %q", networkPluginName) } } else { allErrs = append(allErrs, fmt.Errorf("Network plugin %q not found.", networkPluginName)) } return chosenPlugin, utilerrors.NewAggregate(allErrs) }
// InitNetworkPlugin inits the plugin that matches networkPluginName. Plugins must have unique names. func InitNetworkPlugin(plugins []NetworkPlugin, networkPluginName string, host Host) (NetworkPlugin, error) { if networkPluginName == "" { // default to the no_op plugin plug := &noopNetworkPlugin{} if err := plug.Init(host); err != nil { return nil, err } return plug, nil } pluginMap := map[string]NetworkPlugin{} allErrs := []error{} for _, plugin := range plugins { name := plugin.Name() if !validation.IsQualifiedName(name) { allErrs = append(allErrs, fmt.Errorf("network plugin has invalid name: %#v", plugin)) continue } if _, found := pluginMap[name]; found { allErrs = append(allErrs, fmt.Errorf("network plugin %q was registered more than once", name)) continue } pluginMap[name] = plugin } chosenPlugin := pluginMap[networkPluginName] if chosenPlugin != nil { err := chosenPlugin.Init(host) if err != nil { allErrs = append(allErrs, fmt.Errorf("Network plugin %q failed init: %v", networkPluginName, err)) } else { glog.V(1).Infof("Loaded network plugin %q", networkPluginName) } } else { allErrs = append(allErrs, fmt.Errorf("Network plugin %q not found.", networkPluginName)) } return chosenPlugin, utilerrors.NewAggregate(allErrs) }
func (f *ConfigFactory) getPluginArgs() (*PluginFactoryArgs, error) { failureDomainArgs := strings.Split(f.FailureDomains, ",") for _, failureDomain := range failureDomainArgs { if errs := utilvalidation.IsQualifiedName(failureDomain); len(errs) != 0 { return nil, fmt.Errorf("invalid failure domain: %q: %s", failureDomain, strings.Join(errs, ";")) } } return &PluginFactoryArgs{ PodLister: f.PodLister, ServiceLister: f.ServiceLister, ControllerLister: f.ControllerLister, ReplicaSetLister: f.ReplicaSetLister, // All fit predicates only need to consider schedulable nodes. NodeLister: f.NodeLister.NodeCondition(getNodeConditionPredicate()), NodeInfo: &predicates.CachedNodeInfo{StoreToNodeLister: f.NodeLister}, PVInfo: f.PVLister, PVCInfo: &predicates.CachedPersistentVolumeClaimInfo{StoreToPersistentVolumeClaimLister: f.PVCLister}, HardPodAffinitySymmetricWeight: f.HardPodAffinitySymmetricWeight, FailureDomains: sets.NewString(failureDomainArgs...).List(), }, nil }
func parseTaints(spec []string) ([]api.Taint, []string, error) { var taints []api.Taint var remove []string for _, taintSpec := range spec { if strings.Index(taintSpec, "=") != -1 && strings.Index(taintSpec, ":") != -1 { parts := strings.Split(taintSpec, "=") if len(parts) != 2 || len(parts[1]) == 0 || len(validation.IsQualifiedName(parts[0])) > 0 { return nil, nil, fmt.Errorf("invalid taint spec: %v", taintSpec) } parts2 := strings.Split(parts[1], ":") errs := validation.IsValidLabelValue(parts2[0]) if len(parts2) != 2 || len(errs) != 0 { return nil, nil, fmt.Errorf("invalid taint spec: %v, %s", taintSpec, strings.Join(errs, "; ")) } if parts2[1] != string(api.TaintEffectNoSchedule) && parts2[1] != string(api.TaintEffectPreferNoSchedule) { return nil, nil, fmt.Errorf("invalid taint spec: %v, unsupported taint effect", taintSpec) } effect := api.TaintEffect(parts2[1]) newTaint := api.Taint{ Key: parts[0], Value: parts2[0], Effect: effect, } taints = append(taints, newTaint) } else if strings.HasSuffix(taintSpec, "-") { remove = append(remove, taintSpec[:len(taintSpec)-1]) } else { return nil, nil, fmt.Errorf("unknown taint spec: %v", taintSpec) } } return taints, remove, nil }
func validateLabelKey(k string) error { if len(kvalidation.IsQualifiedName(k)) != 0 { return field.Invalid(field.NewPath("label key"), k, qualifiedNameErrorMsg) } return nil }
func validateLabelKey(k string) error { if !kvalidation.IsQualifiedName(k) { return fielderrors.NewFieldInvalid("label key", k, qualifiedNameErrorMsg) } return nil }
func validateLabelKey(k string) error { if errs := validation.IsQualifiedName(k); len(errs) != 0 { return fmt.Errorf("invalid label key %q: %s", k, strings.Join(errs, "; ")) } return nil }
func validateLabelKey(k string) error { if !validation.IsQualifiedName(k) { return fmt.Errorf("invalid label key: %s", qualifiedNameErrorMsg) } return nil }
// Creates a scheduler from a set of registered fit predicate keys and priority keys. func (f *ConfigFactory) CreateFromKeys(predicateKeys, priorityKeys sets.String, extenders []algorithm.SchedulerExtender) (*scheduler.Config, error) { glog.V(2).Infof("creating scheduler with fit predicates '%v' and priority functions '%v", predicateKeys, priorityKeys) if f.HardPodAffinitySymmetricWeight < 0 || f.HardPodAffinitySymmetricWeight > 100 { return nil, fmt.Errorf("invalid hardPodAffinitySymmetricWeight: %d, must be in the range 0-100", f.HardPodAffinitySymmetricWeight) } failureDomainArgs := strings.Split(f.FailureDomains, ",") for _, failureDomain := range failureDomainArgs { if !utilvalidation.IsQualifiedName(failureDomain) { return nil, fmt.Errorf("invalid failure domain: %s", failureDomain) } } pluginArgs := PluginFactoryArgs{ PodLister: f.PodLister, ServiceLister: f.ServiceLister, ControllerLister: f.ControllerLister, ReplicaSetLister: f.ReplicaSetLister, // All fit predicates only need to consider schedulable nodes. NodeLister: f.NodeLister.NodeCondition(getNodeConditionPredicate()), NodeInfo: &predicates.CachedNodeInfo{StoreToNodeLister: f.NodeLister}, PVInfo: f.PVLister, PVCInfo: f.PVCLister, HardPodAffinitySymmetricWeight: f.HardPodAffinitySymmetricWeight, FailureDomains: sets.NewString(failureDomainArgs...).List(), } predicateFuncs, err := getFitPredicateFunctions(predicateKeys, pluginArgs) if err != nil { return nil, err } priorityConfigs, err := getPriorityFunctionConfigs(priorityKeys, pluginArgs) if err != nil { return nil, err } // Watch and queue pods that need scheduling. cache.NewReflector(f.createUnassignedNonTerminatedPodLW(), &api.Pod{}, f.PodQueue, 0).RunUntil(f.StopEverything) // Begin populating scheduled pods. go f.scheduledPodPopulator.Run(f.StopEverything) // Begin populating nodes. go f.nodePopulator.Run(f.StopEverything) // Watch PVs & PVCs // They may be listed frequently for scheduling constraints, so provide a local up-to-date cache. cache.NewReflector(f.createPersistentVolumeLW(), &api.PersistentVolume{}, f.PVLister.Store, 0).RunUntil(f.StopEverything) cache.NewReflector(f.createPersistentVolumeClaimLW(), &api.PersistentVolumeClaim{}, f.PVCLister.Store, 0).RunUntil(f.StopEverything) // Watch and cache all service objects. Scheduler needs to find all pods // created by the same services or ReplicationControllers/ReplicaSets, so that it can spread them correctly. // Cache this locally. cache.NewReflector(f.createServiceLW(), &api.Service{}, f.ServiceLister.Store, 0).RunUntil(f.StopEverything) // Watch and cache all ReplicationController objects. Scheduler needs to find all pods // created by the same services or ReplicationControllers/ReplicaSets, so that it can spread them correctly. // Cache this locally. cache.NewReflector(f.createControllerLW(), &api.ReplicationController{}, f.ControllerLister.Indexer, 0).RunUntil(f.StopEverything) // Watch and cache all ReplicaSet objects. Scheduler needs to find all pods // created by the same services or ReplicationControllers/ReplicaSets, so that it can spread them correctly. // Cache this locally. cache.NewReflector(f.createReplicaSetLW(), &extensions.ReplicaSet{}, f.ReplicaSetLister.Store, 0).RunUntil(f.StopEverything) r := rand.New(rand.NewSource(time.Now().UnixNano())) algo := scheduler.NewGenericScheduler(f.schedulerCache, predicateFuncs, priorityConfigs, extenders, r) podBackoff := podBackoff{ perPodBackoff: map[types.NamespacedName]*backoffEntry{}, clock: realClock{}, defaultDuration: 1 * time.Second, maxDuration: 60 * time.Second, } return &scheduler.Config{ SchedulerCache: f.schedulerCache, // The scheduler only needs to consider schedulable nodes. NodeLister: f.NodeLister.NodeCondition(getNodeConditionPredicate()), Algorithm: algo, Binder: &binder{f.Client}, NextPod: func() *api.Pod { return f.getNextPod() }, Error: f.makeDefaultErrorFunc(&podBackoff, f.PodQueue), StopEverything: f.StopEverything, }, nil }