import (
"log"
+ "context"
+ "crypto/sha512"
+ //"encoding/json"
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
- "golang.org/x/net/context"
+ "github.com/containernetworking/cni/libcni"
+)
+
+const (
+ EnvCNIPath = "CNI_PATH"
+ EnvNetDir = "NETCONFPATH"
+ //EnvCapabilityArgs = "CAP_ARGS"
+ //EnvCNIArgs = "CNI_ARGS"
+ //EnvCNIIfname = "CNI_IFNAME"
+
+ DefaultNetDir = "/etc/cni/net.d"
+
+ CmdAdd = "add"
+ CmdCheck = "check"
+ CmdDel = "del"
)
// Server represents the gRPC server
func (s *CNIServer) CNIadd(ctx context.Context, in *CNIaddMsg) (*ADDresult, error) {
log.Printf("Receive message Conf file: %s", in.Conf)
-
log.Printf("Receive message ContainerID: %s", in.ContainerID)
log.Printf("Receive message NetNS: %s", in.NetNS)
log.Printf("Receive message IfName: %s", in.IfName)
log.Printf("Receive message CniArgs: %s", in.CniArgs)
+ log.Printf("Receive message CniCapArgs: %s", in.CapArgs)
- cniResult := ADDresult{
- StdOut: "stdOutStringHere",
+ netconf, rt, cninet, err := cniCommon(in.Conf, in.NetNS, in.IfName, in.CniArgs, in.CapArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ result, err := cninet.AddNetworkList(context.TODO(), netconf, rt)
+ if err != nil {
+ return nil, err
+ }
+
+ cniResult := ADDresult{}
+ if result != nil {
+ cniResult.StdOut = result.String()
}
log.Printf("Response from server: %s", cniResult.StdOut)
func (s *CNIServer) CNIcheck(ctx context.Context, in *CNIcheckMsg) (*CHECKresult, error) {
log.Printf("Receive message Conf file: %s", in.Conf)
-
log.Printf("Receive message ContainerID: %s", in.ContainerID)
log.Printf("Receive message NetNS: %s", in.NetNS)
log.Printf("Receive message IfName: %s", in.IfName)
log.Printf("Receive message CniArgs: %s", in.CniArgs)
+ log.Printf("Receive message CniCapArgs: %s", in.CapArgs)
+
+ netconf, rt, cninet, err := cniCommon(in.Conf, in.NetNS, in.IfName, in.CniArgs, in.CapArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ err = cninet.CheckNetworkList(context.TODO(), netconf, rt)
+ if err != nil {
+ return nil, err
+ }
cniResult := CHECKresult{
Error: "",
// CNIdel generates result to a CNIdelMsg
func (s *CNIServer) CNIdel(ctx context.Context, in *CNIdelMsg) (*DELresult, error) {
- log.Printf("Receive message Conf file: %s", in.Conf)
+ log.Printf("Receive message Conf file: %s", in.Conf)
log.Printf("Receive message ContainerID: %s", in.ContainerID)
log.Printf("Receive message NetNS: %s", in.NetNS)
log.Printf("Receive message IfName: %s", in.IfName)
log.Printf("Receive message CniArgs: %s", in.CniArgs)
+ log.Printf("Receive message CniCapArgs: %s", in.CapArgs)
+
+ netconf, rt, cninet, err := cniCommon(in.Conf, in.NetNS, in.IfName, in.CniArgs, in.CapArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ err = cninet.DelNetworkList(context.TODO(), netconf, rt)
+ if err != nil {
+ return nil, err
+ }
cniResult := DELresult{
- StdOut: "stdOutStringHere",
+ Error: "",
}
log.Printf("Response from server: %s", cniResult.StdOut)
return &cniResult, nil
}
+
+func parseArgs(args string) ([][2]string, error) {
+ var result [][2]string
+
+ pairs := strings.Split(args, ";")
+ for _, pair := range pairs {
+ kv := strings.Split(pair, "=")
+ if len(kv) != 2 || kv[0] == "" || kv[1] == "" {
+ return nil, fmt.Errorf("invalid CNI_ARGS pair %q", pair)
+ }
+
+ result = append(result, [2]string{kv[0], kv[1]})
+ }
+
+ return result, nil
+}
+
+func cniCommon(conf string, netns string, ifName string, args string, capabilityArgsValue []*CNIcapArgs) (*libcni.NetworkConfigList, *libcni.RuntimeConf, *libcni.CNIConfig, error) {
+
+ log.Printf("cniCommon Called")
+
+ // TODO
+ //netdir := os.Getenv(EnvNetDir)
+ netdir := "/home/mcambria/go/src/github.com/containernetworking"
+ if netdir == "" {
+ netdir = DefaultNetDir
+ }
+ netconf, err := libcni.LoadConfList(netdir, conf)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+
+ // TODO deal with capabilityArgs
+ //
+ //var capabilityArgs map[string]interface{}
+ // //capabilityArgsValue := os.Getenv(EnvCapabilityArgs)
+ //if len(capabilityArgsValue) > 0 {
+ // if err = json.Unmarshal([]byte(capabilityArgsValue), &capabilityArgs); err != nil {
+ // return nil, nil, nil, err
+ // }
+ //}
+
+ var cniArgs [][2]string
+ if args != "" {
+ if len(args) > 0 {
+ cniArgs, err = parseArgs(args)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ }
+ }
+
+ if ifName == "" {
+ ifName = "eth0"
+ }
+
+ if netns != "" {
+ netns, err = filepath.Abs(netns)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ } else {
+ return nil, nil, nil, fmt.Errorf("network namespace is required")
+ }
+
+ // Generate the containerid by hashing the netns path
+ s := sha512.Sum512([]byte(netns))
+ containerID := fmt.Sprintf("cnitool-%x", s[:10])
+
+ // TODO
+ //cninet := libcni.NewCNIConfig(filepath.SplitList(os.Getenv(EnvCNIPath)), nil)
+ cniBinPath := "/home/mcambria/go/src/github.com/mccv1r0/plugins/bin"
+ cninet := libcni.NewCNIConfig(filepath.SplitList(cniBinPath), nil)
+
+ rt := &libcni.RuntimeConf{
+ ContainerID: containerID,
+ NetNS: netns,
+ IfName: ifName,
+ Args: cniArgs,
+ //CapabilityArgs: capabilityArgs,
+ }
+
+var f *os.File
+var sout string
+f, _ = os.OpenFile("/tmp/check.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
+
+sout = fmt.Sprintf("mcc: cninet: %v of type %T \n", cninet, cninet)
+_, _ = f.Write([]byte(sout))
+sout = fmt.Sprintf("mcc: netconf: %v of type %T \n", netconf, netconf)
+_, _ = f.Write([]byte(sout))
+sout = fmt.Sprintf("mcc: rt: %v of type %T \n", rt, rt)
+_, _ = f.Write([]byte(sout))
+
+ return netconf, rt, cninet, nil
+}
+
+/*
+{
+
+
+ switch os.Args[1] {
+ case CmdAdd:
+ result, err := cninet.AddNetworkList(context.TODO(), netconf, rt)
+ if result != nil {
+ _ = result.Print()
+ }
+ return err
+ case CmdCheck:
+ err := cninet.CheckNetworkList(context.TODO(), netconf, rt)
+ return err
+ case CmdDel:
+ err := cninet.DelNetworkList(context.TODO(), netconf, rt)
+ return err
+ }
+
+ return nil
+}
+*/
+
package main
import (
"log"
+ "context"
+ "crypto/sha512"
+ "encoding/json"
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/containernetworking/cni/libcni"
"github.com/mccv1r0/demo-grpc/api"
- "golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
+const (
+ EnvCNIPath = "CNI_PATH"
+ EnvNetDir = "NETCONFPATH"
+ EnvCapabilityArgs = "CAP_ARGS"
+ EnvCNIArgs = "CNI_ARGS"
+ EnvCNIIfname = "CNI_IFNAME"
+
+ DefaultNetDir = "/etc/cni/net.d"
+
+ CmdAdd = "add"
+ CmdCheck = "check"
+ CmdDel = "del"
+)
+
+
// Authentication holds the login/password
type Authentication struct {
Login string
ConfigPath: &cniPath,
Cmd: api.CmdType_ADD,
ContainerID: "containerOne",
- NetNS: "mcc-test-0",
+ NetNS: "/var/run/netns/mcc-test-0",
IfName: "ensX",
StdIn: "stdInStringHere",
CniArgs: "IgnoreUnknown=1;IP=10.1.0.20",
ConfigPath: &cniPath,
Cmd: api.CmdType_ADD,
ContainerID: "containerOne",
- NetNS: "mcc-test-0",
+ NetNS: "/var/run/netns/mcc-test-0",
IfName: "ensX",
StdIn: "stdInStringHere",
CniArgs: "IgnoreUnknown=1;IP=10.1.0.20",
cniAddMsg := api.CNIaddMsg{
Conf: cniPath.NetConf,
ContainerID: "containerOne",
- NetNS: "mcc-test-0",
+ NetNS: "/var/run/netns/mcc-test-0",
IfName: "ensX",
CniArgs: "IgnoreUnknown=1;IP=10.1.0.20",
return nil
}
-func main() {
+func oldmain() {
err := sendgRPCusingTcp()
if err != nil {
log.Fatalf("error when calling sendRPCusingTcp: %s", err)
log.Fatalf("error when calling sendRPCusingUnix: %s", err2)
}
}
+
+func parseArgs(args string) ([][2]string, error) {
+ var result [][2]string
+
+ pairs := strings.Split(args, ";")
+ for _, pair := range pairs {
+ kv := strings.Split(pair, "=")
+ if len(kv) != 2 || kv[0] == "" || kv[1] == "" {
+ return nil, fmt.Errorf("invalid CNI_ARGS pair %q", pair)
+ }
+
+ result = append(result, [2]string{kv[0], kv[1]})
+ }
+
+ return result, nil
+}
+
+func main() {
+ if len(os.Args) < 4 {
+ usage()
+ return
+ }
+
+ netdir := os.Getenv(EnvNetDir)
+ if netdir == "" {
+ netdir = DefaultNetDir
+ }
+ netconf, err := libcni.LoadConfList(netdir, os.Args[2])
+ if err != nil {
+ exit(err)
+ }
+
+ var capabilityArgs map[string]interface{}
+ capabilityArgsValue := os.Getenv(EnvCapabilityArgs)
+ if len(capabilityArgsValue) > 0 {
+ if err = json.Unmarshal([]byte(capabilityArgsValue), &capabilityArgs); err != nil {
+ exit(err)
+ }
+ }
+
+ var cniArgs [][2]string
+ args := os.Getenv(EnvCNIArgs)
+ if len(args) > 0 {
+ cniArgs, err = parseArgs(args)
+ if err != nil {
+ exit(err)
+ }
+ }
+
+ ifName, ok := os.LookupEnv(EnvCNIIfname)
+ if !ok {
+ ifName = "eth0"
+ }
+
+ netns := os.Args[3]
+ netns, err = filepath.Abs(netns)
+ if err != nil {
+ exit(err)
+ }
+
+ // Generate the containerid by hashing the netns path
+ s := sha512.Sum512([]byte(netns))
+ containerID := fmt.Sprintf("cnitool-%x", s[:10])
+
+ cninet := libcni.NewCNIConfig(filepath.SplitList(os.Getenv(EnvCNIPath)), nil)
+
+ rt := &libcni.RuntimeConf{
+ ContainerID: containerID,
+ NetNS: netns,
+ IfName: ifName,
+ Args: cniArgs,
+ CapabilityArgs: capabilityArgs,
+ }
+
+var f *os.File
+var sout string
+f, _ = os.OpenFile("/tmp/check.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
+
+sout = fmt.Sprintf("mcc: cninet: %v of type %T \n", cninet, cninet)
+_, _ = f.Write([]byte(sout))
+sout = fmt.Sprintf("mcc: netconf: %v of type %T \n", netconf, netconf)
+_, _ = f.Write([]byte(sout))
+sout = fmt.Sprintf("mcc: rt: %v of type %T \n", rt, rt)
+_, _ = f.Write([]byte(sout))
+
+ switch os.Args[1] {
+ case CmdAdd:
+ result, err := cninet.AddNetworkList(context.TODO(), netconf, rt)
+ if result != nil {
+ _ = result.Print()
+ }
+ exit(err)
+ case CmdCheck:
+ err := cninet.CheckNetworkList(context.TODO(), netconf, rt)
+ exit(err)
+ case CmdDel:
+ exit(cninet.DelNetworkList(context.TODO(), netconf, rt))
+ }
+}
+
+func usage() {
+ exe := filepath.Base(os.Args[0])
+
+ fmt.Fprintf(os.Stderr, "%s: Add, check, or remove network interfaces from a network namespace\n", exe)
+ fmt.Fprintf(os.Stderr, " %s add <net> <netns>\n", exe)
+ fmt.Fprintf(os.Stderr, " %s check <net> <netns>\n", exe)
+ fmt.Fprintf(os.Stderr, " %s del <net> <netns>\n", exe)
+ os.Exit(1)
+}
+
+func exit(err error) {
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s\n", err)
+ os.Exit(1)
+ }
+ os.Exit(0)
+}