github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/networking/net_plugin.go (about) 1 // Copyright 2015 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package networking 16 17 import ( 18 "bytes" 19 "encoding/json" 20 "fmt" 21 "os" 22 "os/exec" 23 "path/filepath" 24 "strings" 25 26 cnitypes "github.com/containernetworking/cni/pkg/types" 27 "github.com/hashicorp/errwrap" 28 29 "github.com/rkt/rkt/common" 30 ) 31 32 // TODO(eyakubovich): make this configurable in rkt.conf 33 const UserNetPluginsPath = "/usr/lib/rkt/plugins/net" 34 const BuiltinNetPluginsPath = "usr/lib/rkt/plugins/net" 35 36 func pluginErr(err error, output []byte) error { 37 if _, ok := err.(*exec.ExitError); ok { 38 emsg := cnitypes.Error{} 39 if perr := json.Unmarshal(output, &emsg); perr != nil { 40 return errwrap.Wrap(fmt.Errorf("netplugin failed but error parsing its diagnostic message %q", string(output)), perr) 41 } 42 details := "" 43 if emsg.Details != "" { 44 details = fmt.Sprintf("; %v", emsg.Details) 45 } 46 return fmt.Errorf("%v%v", emsg.Msg, details) 47 } 48 49 return err 50 } 51 52 // Executes a given network plugin. If successful, mutates n.runtime with 53 // the runtime information 54 func (e *podEnv) netPluginAdd(n *activeNet, netns string) error { 55 output, err := e.execNetPlugin("ADD", n, netns) 56 if err != nil { 57 return pluginErr(err, output) 58 } 59 60 pr := cnitypes.Result{} 61 if err = json.Unmarshal(output, &pr); err != nil { 62 err = errwrap.Wrap(fmt.Errorf("parsing %q", string(output)), err) 63 return errwrap.Wrap(fmt.Errorf("error parsing %q result", n.conf.Name), err) 64 } 65 66 if pr.IP4 == nil { 67 return nil // TODO(casey) should this be an error? 68 } 69 70 // All is well - mutate the runtime 71 n.runtime.MergeCNIResult(pr) 72 return nil 73 } 74 75 func (e *podEnv) netPluginDel(n *activeNet, netns string) error { 76 output, err := e.execNetPlugin("DEL", n, netns) 77 if err != nil { 78 return pluginErr(err, output) 79 } 80 return nil 81 } 82 83 func (e *podEnv) pluginPaths() []string { 84 // try 3rd-party path first 85 return []string{ 86 filepath.Join(e.localConfig, UserNetPathSuffix), 87 UserNetPluginsPath, 88 filepath.Join(common.Stage1RootfsPath(e.podRoot), BuiltinNetPluginsPath), 89 } 90 } 91 92 func (e *podEnv) findNetPlugin(plugin string) string { 93 for _, p := range e.pluginPaths() { 94 fullname := filepath.Join(p, plugin) 95 if fi, err := os.Stat(fullname); err == nil && fi.Mode().IsRegular() { 96 return fullname 97 } 98 } 99 100 return "" 101 } 102 103 func envVars(vars [][2]string) []string { 104 env := os.Environ() 105 106 for _, kv := range vars { 107 env = append(env, strings.Join(kv[:], "=")) 108 } 109 110 return env 111 } 112 113 func (e *podEnv) execNetPlugin(cmd string, n *activeNet, netns string) ([]byte, error) { 114 if n.runtime.PluginPath == "" { 115 n.runtime.PluginPath = e.findNetPlugin(n.conf.Type) 116 } 117 if n.runtime.PluginPath == "" { 118 return nil, fmt.Errorf("Could not find plugin %q", n.conf.Type) 119 } 120 121 vars := [][2]string{ 122 {"CNI_VERSION", "0.1.0"}, 123 {"CNI_COMMAND", cmd}, 124 {"CNI_CONTAINERID", e.podID.String()}, 125 {"CNI_NETNS", netns}, 126 {"CNI_ARGS", n.runtime.Args}, 127 {"CNI_IFNAME", n.runtime.IfName}, 128 {"CNI_PATH", strings.Join(e.pluginPaths(), ":")}, 129 } 130 131 stdin := bytes.NewBuffer(n.confBytes) 132 stdout := &bytes.Buffer{} 133 134 c := exec.Cmd{ 135 Path: n.runtime.PluginPath, 136 Args: []string{n.runtime.PluginPath}, 137 Env: envVars(vars), 138 Stdin: stdin, 139 Stdout: stdout, 140 Stderr: os.Stderr, 141 } 142 143 err := c.Run() 144 return stdout.Bytes(), err 145 }