aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/ovn4nfvk8s-cni/ovn4nfvk8s-cni.go6
-rw-r--r--cmd/ovn4nfvk8s/ovn4nfvk8s.go4
-rw-r--r--internal/pkg/config/config.go96
-rw-r--r--internal/pkg/ovn/ovn_test.go82
-rw-r--r--internal/pkg/ovn/pods.go53
5 files changed, 125 insertions, 116 deletions
diff --git a/cmd/ovn4nfvk8s-cni/ovn4nfvk8s-cni.go b/cmd/ovn4nfvk8s-cni/ovn4nfvk8s-cni.go
index 2722eaa..ec37c02 100644
--- a/cmd/ovn4nfvk8s-cni/ovn4nfvk8s-cni.go
+++ b/cmd/ovn4nfvk8s-cni/ovn4nfvk8s-cni.go
@@ -20,7 +20,6 @@ import (
"github.com/containernetworking/cni/pkg/version"
"k8s.io/apimachinery/pkg/util/wait"
- kexec "k8s.io/utils/exec"
"ovn4nfv-k8s-plugin/internal/pkg/kube"
"ovn4nfv-k8s-plugin/cmd/ovn4nfvk8s-cni/app"
@@ -128,7 +127,7 @@ func addMultipleInterfaces(args *skel.CmdArgs, ovnAnnotation, namespace, podName
gatewayIP := ovnNet["gateway_ip"]
defaultGateway := ovnNet["defaultGateway"]
- if ipAddress == "" || macAddress == "" || gatewayIP == "" {
+ if ipAddress == "" || macAddress == "" {
logrus.Errorf("failed in pod annotation key extract")
return nil
}
@@ -323,9 +322,8 @@ func main() {
c.Version = "0.0.2"
c.Flags = config.Flags
- exec := kexec.New()
c.Action = func(ctx *cli.Context) error {
- if _, err := config.InitConfig(ctx, exec, nil); err != nil {
+ if _, err := config.InitConfig(ctx); err != nil {
return err
}
diff --git a/cmd/ovn4nfvk8s/ovn4nfvk8s.go b/cmd/ovn4nfvk8s/ovn4nfvk8s.go
index d097558..0c0cc2e 100644
--- a/cmd/ovn4nfvk8s/ovn4nfvk8s.go
+++ b/cmd/ovn4nfvk8s/ovn4nfvk8s.go
@@ -22,7 +22,6 @@ func main() {
c := cli.NewApp()
c.Name = "ovn4nfvk8s"
c.Usage = "run ovn4nfvk8s to start pod watchers"
- c.Version = config.Version
c.Flags = append([]cli.Flag{
// Daemon file
cli.StringFlag{
@@ -50,9 +49,8 @@ func delPidfile(pidfile string) {
}
func runOvnKube(ctx *cli.Context) error {
- fmt.Println("ovn4nfvk8s started")
exec := kexec.New()
- _, err := config.InitConfig(ctx, exec, nil)
+ _, err := config.InitConfig(ctx)
if err != nil {
return err
}
diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go
index 045a0ac..b73dd9d 100644
--- a/internal/pkg/config/config.go
+++ b/internal/pkg/config/config.go
@@ -2,28 +2,21 @@ package config
import (
"fmt"
- "net/url"
"os"
"path/filepath"
"reflect"
- "strings"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
gcfg "gopkg.in/gcfg.v1"
- kexec "k8s.io/utils/exec"
-
- "k8s.io/client-go/kubernetes"
+ "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
- "k8s.io/client-go/util/cert"
)
// The following are global config parameters that other modules may access directly
var (
- // ovn-kubernetes version, to be changed with every release
- Version = "0.3.0"
// Default holds parsed config file parameters and command-line overrides
Default = DefaultConfig{
@@ -42,10 +35,8 @@ var (
Plugin: "ovn4nfvk8s-cni",
}
- // Kubernetes holds Kubernetes-related parsed config file parameters and command-line overrides
- Kubernetes = KubernetesConfig{
- APIServer: "http://localhost:8080",
- }
+ // Kubernetes holds Kubernetes-related parsed config file parameters
+ Kubernetes = KubernetesConfig{}
)
// DefaultConfig holds parsed config file parameters and command-line overrides
@@ -73,9 +64,6 @@ type CNIConfig struct {
// KubernetesConfig holds Kubernetes-related parsed config file parameters and command-line overrides
type KubernetesConfig struct {
Kubeconfig string `gcfg:"kubeconfig"`
- CACert string `gcfg:"cacert"`
- APIServer string `gcfg:"apiserver"`
- Token string `gcfg:"token"`
}
// Config is used to read the structured config file and to cache config in testcases
@@ -164,57 +152,21 @@ var Flags = []cli.Flag{
// Kubernetes-related options
cli.StringFlag{
Name: "k8s-kubeconfig",
- Usage: "absolute path to the Kubernetes kubeconfig file (not required if the --k8s-apiserver, --k8s-ca-cert, and --k8s-token are given)",
+ Usage: "absolute path to the Kubernetes kubeconfig file",
Destination: &cliConfig.Kubernetes.Kubeconfig,
},
- cli.StringFlag{
- Name: "k8s-apiserver",
- Usage: "URL of the Kubernetes API server (not required if --k8s-kubeconfig is given) (default: http://localhost:8443)",
- Destination: &cliConfig.Kubernetes.APIServer,
- },
- cli.StringFlag{
- Name: "k8s-cacert",
- Usage: "the absolute path to the Kubernetes API CA certificate (not required if --k8s-kubeconfig is given)",
- Destination: &cliConfig.Kubernetes.CACert,
- },
- cli.StringFlag{
- Name: "k8s-token",
- Usage: "the Kubernetes API authentication token (not required if --k8s-kubeconfig is given)",
- Destination: &cliConfig.Kubernetes.Token,
- },
-}
-
-type Defaults struct {
- K8sAPIServer bool
- K8sToken bool
- K8sCert bool
}
-const (
- ovsVsctlCommand = "ovs-vsctl"
-)
-
-func buildKubernetesConfig(exec kexec.Interface, cli, file *config, defaults *Defaults) error {
+func buildKubernetesConfig(cli, file *config) error {
// Copy config file values over default values
overrideFields(&Kubernetes, &file.Kubernetes)
// And CLI overrides over config file and default values
overrideFields(&Kubernetes, &cli.Kubernetes)
- if Kubernetes.Kubeconfig != "" && !pathExists(Kubernetes.Kubeconfig) {
+ if Kubernetes.Kubeconfig == "" || !pathExists(Kubernetes.Kubeconfig) {
return fmt.Errorf("kubernetes kubeconfig file %q not found", Kubernetes.Kubeconfig)
}
- if Kubernetes.CACert != "" && !pathExists(Kubernetes.CACert) {
- return fmt.Errorf("kubernetes CA certificate file %q not found", Kubernetes.CACert)
- }
-
- url, err := url.Parse(Kubernetes.APIServer)
- if err != nil {
- return fmt.Errorf("kubernetes API server address %q invalid: %v", Kubernetes.APIServer, err)
- } else if url.Scheme != "https" && url.Scheme != "http" {
- return fmt.Errorf("kubernetes API server URL scheme %q invalid", url.Scheme)
- }
-
return nil
}
@@ -235,15 +187,15 @@ func getConfigFilePath(ctx *cli.Context) (string, bool) {
// InitConfig reads the config file and common command-line options and
// constructs the global config object from them. It returns the config file
// path (if explicitly specified) or an error
-func InitConfig(ctx *cli.Context, exec kexec.Interface, defaults *Defaults) (string, error) {
- return InitConfigWithPath(ctx, exec, "", defaults)
+func InitConfig(ctx *cli.Context) (string, error) {
+ return InitConfigWithPath(ctx, "")
}
// InitConfigWithPath reads the given config file (or if empty, reads the config file
// specified by command-line arguments, or empty, the default config file) and
// common command-line options and constructs the global config object from
// them. It returns the config file path (if explicitly specified) or an error
-func InitConfigWithPath(ctx *cli.Context, exec kexec.Interface, configFile string, defaults *Defaults) (string, error) {
+func InitConfigWithPath(ctx *cli.Context, configFile string) (string, error) {
var cfg config
var retConfigFile string
var configFileIsDefault bool
@@ -277,10 +229,6 @@ func InitConfigWithPath(ctx *cli.Context, exec kexec.Interface, configFile strin
logrus.Infof("Parsed config: %+v", cfg)
}
- if defaults == nil {
- defaults = &Defaults{}
- }
-
// Build config that needs no special processing
overrideFields(&Default, &cfg.Default)
overrideFields(&Default, &cliConfig.Default)
@@ -301,7 +249,7 @@ func InitConfigWithPath(ctx *cli.Context, exec kexec.Interface, configFile strin
}
}
- if err = buildKubernetesConfig(exec, &cliConfig, &cfg, defaults); err != nil {
+ if err = buildKubernetesConfig(&cliConfig, &cfg); err != nil {
return "", err
}
logrus.Debugf("Default config: %+v", Default)
@@ -320,8 +268,7 @@ func pathExists(path string) bool {
return true
}
-// NewClientset creates a Kubernetes clientset from either a kubeconfig,
-// TLS properties, or an apiserver URL
+// NewClientset creates a Kubernetes clientset
func NewClientset(conf *KubernetesConfig) (*kubernetes.Clientset, error) {
var kconfig *rest.Config
var err error
@@ -329,27 +276,6 @@ func NewClientset(conf *KubernetesConfig) (*kubernetes.Clientset, error) {
if conf.Kubeconfig != "" {
// uses the current context in kubeconfig
kconfig, err = clientcmd.BuildConfigFromFlags("", conf.Kubeconfig)
- } else if strings.HasPrefix(conf.APIServer, "https") {
- if conf.APIServer == "" || conf.Token == "" {
- return nil, fmt.Errorf("TLS-secured apiservers require token and CA certificate")
- }
- kconfig = &rest.Config{
- Host: conf.APIServer,
- BearerToken: conf.Token,
- }
- if conf.CACert != "" {
- if _, err := cert.NewPool(conf.CACert); err != nil {
- return nil, err
- }
- kconfig.TLSClientConfig = rest.TLSClientConfig{CAFile: conf.CACert}
- }
- } else if strings.HasPrefix(conf.APIServer, "http") {
- kconfig, err = clientcmd.BuildConfigFromFlags(conf.APIServer, "")
- } else {
- // Assume we are running from a container managed by kubernetes
- // and read the apiserver address and tokens from the
- // container's environment.
- kconfig, err = rest.InClusterConfig()
}
if err != nil {
return nil, err
diff --git a/internal/pkg/ovn/ovn_test.go b/internal/pkg/ovn/ovn_test.go
index 2e558a6..f974c30 100644
--- a/internal/pkg/ovn/ovn_test.go
+++ b/internal/pkg/ovn/ovn_test.go
@@ -31,8 +31,6 @@ var _ = Describe("Add logical Port", func() {
var app *cli.App
BeforeEach(func() {
- // Restore global default values before each testcase
- //config.RestoreDefaultConfig()
app = cli.NewApp()
app.Name = "test"
@@ -57,13 +55,13 @@ var _ = Describe("Add logical Port", func() {
})
fakeCmds = ovntest.AddFakeCmd(fakeCmds, &ovntest.ExpectedCmd{
- Cmd: "ovn-nbctl --timeout=15 --if-exists get logical_switch " + netName + " external_ids:gateway_ip",
- Output: gwCIDR,
- })
- fakeCmds = ovntest.AddFakeCmd(fakeCmds, &ovntest.ExpectedCmd{
Cmd: "ovn-nbctl --timeout=15 get logical_switch_port " + portName + " dynamic_addresses",
Output: macIPAddress,
})
+ fakeCmds = ovntest.AddFakeCmd(fakeCmds, &ovntest.ExpectedCmd{
+ Cmd: "ovn-nbctl --timeout=15 --if-exists get logical_switch " + netName + " external_ids:gateway_ip",
+ Output: gwCIDR,
+ })
fexec := &fakeexec.FakeExec{
CommandScript: fakeCmds,
@@ -75,9 +73,6 @@ var _ = Describe("Add logical Port", func() {
err := util.SetExec(fexec)
Expect(err).NotTo(HaveOccurred())
- _, err = config.InitConfig(ctx, fexec, nil)
- Expect(err).NotTo(HaveOccurred())
-
fakeClient := &fake.Clientset{}
var fakeWatchFactory factory.WatchFactory
@@ -105,7 +100,7 @@ var _ = Describe("Add logical Port", func() {
)
ovnController.addLogicalPort(&okPod)
- _, _ = ovnController.kube.GetAnnotationsOnPod("", "ok")
+ Expect(fexec.CommandCalls).To(Equal(len(fakeCmds)))
return nil
}
@@ -113,4 +108,71 @@ var _ = Describe("Add logical Port", func() {
err := app.Run([]string{app.Name})
Expect(err).NotTo(HaveOccurred())
})
+
+ It("tests Pod provider", func() {
+ app.Action = func(ctx *cli.Context) error {
+ const (
+ gwIP string = "10.1.1.1"
+ gwCIDR string = gwIP + "/24"
+ netName string = "ovn-prot-net"
+ portName string = "_ok_net0"
+ macIPAddress string = "0a:00:00:00:00:01 192.168.1.3/24"
+ )
+ fakeCmds := ovntest.AddFakeCmd(nil, &ovntest.ExpectedCmd{
+ Cmd: "ovn-nbctl --timeout=15 --data=bare --no-heading --columns=name find logical_switch " + "name=" + netName,
+ Output: netName,
+ })
+
+ fakeCmds = ovntest.AddFakeCmdsNoOutputNoError(fakeCmds, []string{
+ "ovn-nbctl --timeout=15 --may-exist lsp-add " + netName + " " + portName + " -- lsp-set-addresses " + portName + " " + macIPAddress + " -- --if-exists clear logical_switch_port " + portName + " dynamic_addresses" + " -- set logical_switch_port " + portName + " external-ids:namespace= external-ids:logical_switch=" + netName + " external-ids:pod=true",
+ })
+
+ fakeCmds = ovntest.AddFakeCmd(fakeCmds, &ovntest.ExpectedCmd{
+ Cmd: "ovn-nbctl --timeout=15 get logical_switch_port " + portName + " addresses",
+ Output: macIPAddress,
+ })
+
+ fexec := &fakeexec.FakeExec{
+ CommandScript: fakeCmds,
+ LookPathFunc: func(file string) (string, error) {
+ return fmt.Sprintf("/fake-bin/%s", file), nil
+ },
+ }
+ err := util.SetExec(fexec)
+ Expect(err).NotTo(HaveOccurred())
+
+ fakeClient := &fake.Clientset{}
+ var fakeWatchFactory factory.WatchFactory
+
+ ovnController := NewOvnController(fakeClient, &fakeWatchFactory)
+ var (
+ okPod = v1.Pod{
+ TypeMeta: metav1.TypeMeta{
+ Kind: "Pod",
+ APIVersion: "v1",
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "ok",
+ Annotations: map[string]string{"ovnNetwork": "[{ \"name\": \"ovn-prot-net\", \"interface\": \"net0\", \"netType\": \"provider\", \"ipAddress\": \"192.168.1.3/24\", \"macAddress\": \"0a:00:00:00:00:01\" }]"},
+ },
+ Spec: v1.PodSpec{
+ Containers: []v1.Container{
+ {
+ Name: "by-name",
+ },
+ {},
+ },
+ },
+ }
+ )
+ ovnController.addLogicalPort(&okPod)
+ Expect(fexec.CommandCalls).To(Equal(len(fakeCmds)))
+
+ return nil
+ }
+
+ err := app.Run([]string{app.Name})
+ Expect(err).NotTo(HaveOccurred())
+ })
+
})
diff --git a/internal/pkg/ovn/pods.go b/internal/pkg/ovn/pods.go
index cc3d459..fcd258e 100644
--- a/internal/pkg/ovn/pods.go
+++ b/internal/pkg/ovn/pods.go
@@ -80,7 +80,7 @@ func (oc *Controller) deleteLogicalPort(pod *kapi.Pod) {
return
}
-func (oc *Controller) addLogicalPortWithSwitch(pod *kapi.Pod, logicalSwitch, ipAddress, macAddress, interfaceName string) (annotation string) {
+func (oc *Controller) addLogicalPortWithSwitch(pod *kapi.Pod, logicalSwitch, ipAddress, macAddress, interfaceName, netType string) (annotation string) {
var out, stderr string
var err error
var isStaticIP bool
@@ -112,7 +112,11 @@ func (oc *Controller) addLogicalPortWithSwitch(pod *kapi.Pod, logicalSwitch, ipA
out, stderr, err = util.RunOVNNbctlUnix("--may-exist", "lsp-add",
logicalSwitch, portName, "--", "lsp-set-addresses", portName,
fmt.Sprintf("%s %s", macAddress, ipAddress), "--", "--if-exists",
- "clear", "logical_switch_port", portName, "dynamic_addresses")
+ "clear", "logical_switch_port", portName, "dynamic_addresses", "--", "set",
+ "logical_switch_port", portName,
+ "external-ids:namespace="+pod.Namespace,
+ "external-ids:logical_switch="+logicalSwitch,
+ "external-ids:pod=true")
if err != nil {
logrus.Errorf("Failed to add logical port to switch "+
"stdout: %q, stderr: %q (%v)",
@@ -136,11 +140,6 @@ func (oc *Controller) addLogicalPortWithSwitch(pod *kapi.Pod, logicalSwitch, ipA
}
}
oc.logicalPortCache[portName] = logicalSwitch
- gatewayIP, mask, err := oc.getGatewayFromSwitch(logicalSwitch)
- if err != nil {
- logrus.Errorf("Error obtaining gateway address for switch %s: %s", logicalSwitch, err)
- return
- }
count := 30
for count > 0 {
@@ -178,7 +177,18 @@ func (oc *Controller) addLogicalPortWithSwitch(pod *kapi.Pod, logicalSwitch, ipA
logrus.Errorf("Error while obtaining addresses for %s", portName)
return
}
- annotation = fmt.Sprintf(`{\"ip_address\":\"%s/%s\", \"mac_address\":\"%s\", \"gateway_ip\": \"%s\"}`, addresses[1], mask, addresses[0], gatewayIP)
+
+ if netType == "virtual" {
+ gatewayIP, mask, err := oc.getGatewayFromSwitch(logicalSwitch)
+ if err != nil {
+ logrus.Errorf("Error obtaining gateway address for switch %s: %s", logicalSwitch, err)
+ return
+ }
+ annotation = fmt.Sprintf(`{\"ip_address\":\"%s/%s\", \"mac_address\":\"%s\", \"gateway_ip\": \"%s\"}`, addresses[1], mask, addresses[0], gatewayIP)
+ } else {
+ annotation = fmt.Sprintf(`{\"ip_address\":\"%s\", \"mac_address\":\"%s\", \"gateway_ip\": \"%s\"}`, addresses[1], addresses[0], "")
+ }
+
return annotation
}
@@ -203,7 +213,7 @@ func findLogicalSwitch(name string) bool {
func (oc *Controller) addLogicalPort(pod *kapi.Pod) {
var logicalSwitch string
- var ipAddress, macAddress, interfaceName, defaultGateway string
+ var ipAddress, macAddress, interfaceName, defaultGateway, netType string
annotation := pod.Annotations["ovnNetwork"]
@@ -217,10 +227,15 @@ func (oc *Controller) addLogicalPort(pod *kapi.Pod) {
ovnString = "["
for _, net := range ovnNetObjs {
logicalSwitch = net["name"].(string)
+ if !findLogicalSwitch(logicalSwitch) {
+ logrus.Errorf("Logical Switch not found")
+ return
+ }
if _, ok := net["interface"]; ok {
interfaceName = net["interface"].(string)
} else {
- interfaceName = ""
+ logrus.Errorf("Interface name must be provided")
+ return
}
if _, ok := net["ipAddress"]; ok {
ipAddress = net["ipAddress"].(string)
@@ -237,14 +252,24 @@ func (oc *Controller) addLogicalPort(pod *kapi.Pod) {
} else {
defaultGateway = "false"
}
- if !findLogicalSwitch(logicalSwitch) {
+ if _, ok := net["netType"]; ok {
+ netType = net["netType"].(string)
+ } else {
+ netType = "virtual"
+ }
+ if netType != "provider" && netType != "virtual" {
+ logrus.Errorf("netType is not supported")
return
}
- if interfaceName == "" {
- logrus.Errorf("Interface name must be provided")
+ if netType == "provider" && ipAddress == "" {
+ logrus.Errorf("ipAddress must be provided for netType Provider")
+ return
+ }
+ if netType == "provider" && defaultGateway == "true" {
+ logrus.Errorf("defaultGateway not supported for provider network - Use ovnNetworkRoutes to add routes")
return
}
- outStr = oc.addLogicalPortWithSwitch(pod, logicalSwitch, ipAddress, macAddress, interfaceName)
+ outStr = oc.addLogicalPortWithSwitch(pod, logicalSwitch, ipAddress, macAddress, interfaceName, netType)
if outStr == "" {
return
}