package keepalived import ( "fmt" "strings" "github.com/golang/glog" kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/runtime" "github.com/openshift/origin/pkg/cmd/util/clientcmd" deployapi "github.com/openshift/origin/pkg/deploy/api" "github.com/openshift/origin/pkg/generate/app" "github.com/openshift/origin/pkg/ipfailover" ) // KeepalivedPlugin is an IP Failover configurator plugin for keepalived sidecar. type KeepalivedPlugin struct { Name string Factory *clientcmd.Factory Options *ipfailover.IPFailoverConfigCmdOptions } // NewIPFailoverConfiguratorPlugin creates a new IPFailoverConfigurator (keepalived) plugin instance. func NewIPFailoverConfiguratorPlugin(name string, f *clientcmd.Factory, options *ipfailover.IPFailoverConfigCmdOptions) (*KeepalivedPlugin, error) { glog.V(4).Infof("Creating new KeepAlived plugin: %q", name) p := &KeepalivedPlugin{ Name: name, Factory: f, Options: options, } return p, nil } // GetWatchPort gets the port to monitor for the IP Failover configuration. func (p *KeepalivedPlugin) GetWatchPort() (int, error) { port := p.Options.WatchPort if port < 1 || port > 65535 { glog.V(4).Infof("Warning: KeepAlived IP Failover config: %q - WatchPort: %d invalid, will default to %d", p.Name, port, ipfailover.DefaultWatchPort) port = ipfailover.DefaultWatchPort } glog.V(4).Infof("KeepAlived IP Failover config: %q - WatchPort: %d", p.Name, port) return port, nil } // GetSelector gets the selector associated with this IP Failover configurator plugin. func (p *KeepalivedPlugin) GetSelector() (map[string]string, error) { labels := make(map[string]string, 0) if p.Options.Selector == ipfailover.DefaultSelector { return map[string]string{ipfailover.DefaultName: p.Name}, nil } labels, remove, err := app.LabelsFromSpec(strings.Split(p.Options.Selector, ",")) if err != nil { return labels, err } if len(remove) > 0 { return labels, fmt.Errorf("you may not pass negative labels in %q", p.Options.Selector) } glog.V(4).Infof("KeepAlived IP Failover config: %q - selector: %+v", p.Name, labels) return labels, nil } // GetNamespace gets the namespace associated with this IP Failover configurator plugin. func (p *KeepalivedPlugin) GetNamespace() (string, error) { namespace, _, err := p.Factory.OpenShiftClientConfig.Namespace() if err != nil { return "", err } glog.V(4).Infof("KeepAlived IP Failover config: %q - namespace: %q", p.Name, namespace) return namespace, nil } // GetDeploymentConfig gets the deployment config associated with this IP Failover configurator plugin. func (p *KeepalivedPlugin) GetDeploymentConfig() (*deployapi.DeploymentConfig, error) { osClient, _, _, err := p.Factory.Clients() if err != nil { return nil, fmt.Errorf("error getting client: %v", err) } namespace, err := p.GetNamespace() if err != nil { return nil, fmt.Errorf("error getting namespace: %v", err) } dc, err := osClient.DeploymentConfigs(namespace).Get(p.Name) if err != nil { if errors.IsNotFound(err) { glog.V(4).Infof("KeepAlived IP Failover DeploymentConfig: %s not found", p.Name) return nil, nil } return nil, fmt.Errorf("error getting KeepAlived IP Failover DeploymentConfig %q: %v", p.Name, err) } glog.V(4).Infof("KeepAlived IP Failover DeploymentConfig: %q = %+v", p.Name, dc) return dc, nil } // Generate the config and services for this IP Failover configuration plugin. func (p *KeepalivedPlugin) Generate() (*kapi.List, error) { selector, err := p.GetSelector() if err != nil { return nil, fmt.Errorf("error getting selector: %v", err) } if len(p.Options.VirtualIPs) == 0 { return nil, fmt.Errorf("you must specify at least one virtual IP address for keepalived to expose") } dc, err := GenerateDeploymentConfig(p.Name, p.Options, selector) if err != nil { return nil, fmt.Errorf("error generating DeploymentConfig: %v", err) } configList := &kapi.List{Items: []runtime.Object{dc}} glog.V(4).Infof("KeepAlived IP Failover DeploymentConfig: %q - generated config: %+v", p.Name, configList) return configList, nil }