diff options
Diffstat (limited to 'src/k8splugin/plugins/ovn4nfvk8s-network/plugin.go')
-rw-r--r-- | src/k8splugin/plugins/ovn4nfvk8s-network/plugin.go | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/src/k8splugin/plugins/ovn4nfvk8s-network/plugin.go b/src/k8splugin/plugins/ovn4nfvk8s-network/plugin.go new file mode 100644 index 00000000..959586bc --- /dev/null +++ b/src/k8splugin/plugins/ovn4nfvk8s-network/plugin.go @@ -0,0 +1,157 @@ +/* +Copyright 2018 Intel Corporation. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "bytes" + "fmt" + kexec "k8s.io/utils/exec" + "os" + + pkgerrors "github.com/pkg/errors" + "k8splugin/plugins/network/v1" + "log" + "strings" + "unicode" + + "math/rand" + "time" +) + +const ( + ovn4nfvRouter = "ovn4nfv-master" + ovnNbctlCommand = "ovn-nbctl" +) + +type OVNNbctler interface { + Run(args ...string) (string, string, error) +} + +type OVNNbctl struct { + run func(args ...string) (string, string, error) + exec kexec.Interface + path string +} + +// Run a command via ovn-nbctl +func (ctl *OVNNbctl) Run(args ...string) (string, string, error) { + if ctl.path == "" { + nbctlPath, err := ctl.exec.LookPath(ovnNbctlCommand) + if err != nil { + return "", "", pkgerrors.Wrap(err, "Look nbctl path error") + } + ctl.path = nbctlPath + } + if ctl.exec == nil { + ctl.exec = kexec.New() + } + + stdout := &bytes.Buffer{} + stderr := &bytes.Buffer{} + cmd := ctl.exec.Command(ctl.path, args...) + cmd.SetStdout(stdout) + cmd.SetStderr(stderr) + err := cmd.Run() + + return strings.Trim(strings.TrimFunc(stdout.String(), unicode.IsSpace), "\""), + stderr.String(), err +} + +var ovnCmd OVNNbctler + +func init() { + ovnCmd = &OVNNbctl{} +} + +// CreateNetwork in OVN controller +func CreateNetwork(network *v1.OnapNetwork) (string, error) { + config, err := network.DecodeConfig() + if err != nil { + return "", err + } + + name := config["name"].(string) + if name == "" { + return "", pkgerrors.New("Empty Name value") + } + + subnet := config["subnet"].(string) + if subnet == "" { + return "", pkgerrors.New("Empty Subnet value") + } + + gatewayIPMask := config["gateway"].(string) + if gatewayIPMask == "" { + return "", pkgerrors.New("Empty Gateway IP Mask") + } + + routerMac, stderr, err := ovnCmd.Run(getAuthStr(), "--if-exist", "-v", "get", "logical_router_port", "rtos-"+name, "mac") + if err != nil { + return "", pkgerrors.Wrapf(err, "Failed to get logical router port,stderr: %q, error: %v", stderr, err) + } + + if routerMac == "" { + log.Print("Generate MAC address") + prefix := "00:00:00" + newRand := rand.New(rand.NewSource(time.Now().UnixNano())) + routerMac = fmt.Sprintf("%s:%02x:%02x:%02x", prefix, newRand.Intn(255), newRand.Intn(255), newRand.Intn(255)) + } + + _, stderr, err = ovnCmd.Run(getAuthStr(), "--may-exist", "lrp-add", ovn4nfvRouter, "rtos-"+name, routerMac, gatewayIPMask) + if err != nil { + return "", pkgerrors.Wrapf(err, "Failed to add logical port to router, stderr: %q, error: %v", stderr, err) + } + + // Create a logical switch and set its subnet. + stdout, stderr, err := ovnCmd.Run(getAuthStr(), "--", "--may-exist", "ls-add", name, "--", "set", "logical_switch", name, "other-config:subnet="+subnet, "external-ids:gateway_ip="+gatewayIPMask) + if err != nil { + return "", pkgerrors.Wrapf(err, "Failed to create a logical switch %v, stdout: %q, stderr: %q, error: %v", name, stdout, stderr, err) + } + + // Connect the switch to the router. + stdout, stderr, err = ovnCmd.Run(getAuthStr(), "--", "--may-exist", "lsp-add", name, "stor-"+name, "--", "set", "logical_switch_port", "stor-"+name, "type=router", "options:router-port=rtos-"+name, "addresses="+"\""+routerMac+"\"") + if err != nil { + return "", pkgerrors.Wrapf(err, "Failed to add logical port to switch, stdout: %q, stderr: %q, error: %v", stdout, stderr, err) + } + + return name, nil +} + +// DeleteNetwork in OVN controller +func DeleteNetwork(name string) error { + log.Printf("Deleting Network: Ovn4nfvk8s %s", name) + + stdout, stderr, err := ovnCmd.Run(getAuthStr(), "--if-exist", "ls-del", name) + if err != nil { + return pkgerrors.Wrapf(err, "Failed to delete switch %v, stdout: %q, stderr: %q, error: %v", name, stdout, stderr, err) + } + + stdout, stderr, err = ovnCmd.Run(getAuthStr(), "--if-exist", "lrp-del", "rtos-"+name) + if err != nil { + return pkgerrors.Wrapf(err, "Failed to delete router port %v, stdout: %q, stderr: %q, error: %v", name, stdout, stderr, err) + } + + stdout, stderr, err = ovnCmd.Run(getAuthStr(), "--if-exist", "lsp-del", "stor-"+name) + if err != nil { + return pkgerrors.Wrapf(err, "Failed to delete switch port %v, stdout: %q, stderr: %q, error: %v", name, stdout, stderr, err) + } + + return nil +} + +func getAuthStr() string { + //TODO: Remove hardcoding: Use ESR data passed to Initialize + ovnCentralAddress := os.Getenv("OVN_CENTRAL_ADDRESS") + return "--db=tcp:" + ovnCentralAddress +} |