mirror of
https://github.com/clearlinux/rkt.git
synced 2026-08-18 21:16:13 +00:00
cb524d42e4
networking: load only *.conf files
247 lines
5.2 KiB
Go
247 lines
5.2 KiB
Go
// Copyright 2015 The rkt Authors
|
|
//
|
|
// 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 networking
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"net"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/cni/pkg/plugin"
|
|
"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types"
|
|
|
|
"github.com/coreos/rkt/common"
|
|
"github.com/coreos/rkt/networking/netinfo"
|
|
)
|
|
|
|
const (
|
|
// Absolute path where users place their net configs
|
|
UserNetPath = "/etc/rkt/net.d"
|
|
|
|
// Default net path relative to stage1 root
|
|
DefaultNetPath = "etc/rkt/net.d/99-default.conf"
|
|
)
|
|
|
|
// "base" struct that's populated from the beginning
|
|
// describing the environment in which the pod
|
|
// is running in
|
|
type podEnv struct {
|
|
podRoot string
|
|
podID types.UUID
|
|
}
|
|
|
|
type activeNet struct {
|
|
confBytes []byte
|
|
conf *plugin.NetConf
|
|
runtime *netinfo.NetInfo
|
|
hostIP net.IP // kludge for default network
|
|
}
|
|
|
|
// Loads nets specified by user and default one from stage1
|
|
func (e *podEnv) loadNets() ([]activeNet, error) {
|
|
nets, err := loadUserNets()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !netExists(nets, "default") {
|
|
defPath := path.Join(common.Stage1RootfsPath(e.podRoot), DefaultNetPath)
|
|
n, err := loadNet(defPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
nets = append(nets, *n)
|
|
}
|
|
|
|
return nets, nil
|
|
}
|
|
|
|
func (e *podEnv) podNSPath() string {
|
|
return filepath.Join(e.podRoot, "netns")
|
|
}
|
|
|
|
func (e *podEnv) netDir() string {
|
|
return filepath.Join(e.podRoot, "net")
|
|
}
|
|
|
|
func (e *podEnv) setupNets(nets []activeNet) error {
|
|
err := os.MkdirAll(e.netDir(), 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
i := 0
|
|
defer func() {
|
|
if err != nil {
|
|
e.teardownNets(nets[:i])
|
|
}
|
|
}()
|
|
|
|
nspath := e.podNSPath()
|
|
|
|
n := activeNet{}
|
|
for i, n = range nets {
|
|
log.Printf("Setup: executing net-plugin %v", n.conf.Type)
|
|
|
|
n.runtime.IfName = fmt.Sprintf(ifnamePattern, i)
|
|
if n.runtime.ConfPath, err = copyFileToDir(n.runtime.ConfPath, e.netDir()); err != nil {
|
|
return fmt.Errorf("error copying %q to %q: %v", n.runtime.ConfPath, e.netDir(), err)
|
|
}
|
|
|
|
n.runtime.IP, n.hostIP, err = e.netPluginAdd(&n, nspath)
|
|
if err != nil {
|
|
return fmt.Errorf("error adding network %q: %v", n.conf.Name, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (e *podEnv) teardownNets(nets []activeNet) {
|
|
nspath := e.podNSPath()
|
|
|
|
for i := len(nets) - 1; i >= 0; i-- {
|
|
log.Printf("Teardown: executing net-plugin %v", nets[i].conf.Type)
|
|
|
|
err := e.netPluginDel(&nets[i], nspath)
|
|
if err != nil {
|
|
log.Printf("Error deleting %q: %v", nets[i].conf.Name, err)
|
|
}
|
|
|
|
// Delete the conf file to signal that the network was
|
|
// torn down (or at least attempted to)
|
|
if err = os.Remove(nets[i].runtime.ConfPath); err != nil {
|
|
log.Printf("Error deleting %q: %v", nets[i].runtime.ConfPath, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func listFiles(dir string) ([]string, error) {
|
|
dirents, err := ioutil.ReadDir(dir)
|
|
switch {
|
|
case err == nil:
|
|
case os.IsNotExist(err):
|
|
return nil, nil
|
|
default:
|
|
return nil, err
|
|
}
|
|
|
|
files := []string{}
|
|
for _, dent := range dirents {
|
|
if dent.IsDir() {
|
|
continue
|
|
}
|
|
|
|
files = append(files, dent.Name())
|
|
}
|
|
|
|
return files, nil
|
|
}
|
|
|
|
func netExists(nets []activeNet, name string) bool {
|
|
for _, n := range nets {
|
|
if n.conf.Name == name {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func loadNet(filepath string) (*activeNet, error) {
|
|
bytes, err := ioutil.ReadFile(filepath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
n := &plugin.NetConf{}
|
|
if err = json.Unmarshal(bytes, n); err != nil {
|
|
return nil, fmt.Errorf("error loading %v: %v", filepath, err)
|
|
}
|
|
|
|
return &activeNet{
|
|
confBytes: bytes,
|
|
conf: n,
|
|
runtime: &netinfo.NetInfo{
|
|
NetName: n.Name,
|
|
ConfPath: filepath,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func copyFileToDir(src, dstdir string) (string, error) {
|
|
dst := filepath.Join(dstdir, filepath.Base(src))
|
|
|
|
s, err := os.Open(src)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer s.Close()
|
|
|
|
d, err := os.Create(dst)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer d.Close()
|
|
|
|
_, err = io.Copy(d, s)
|
|
return dst, err
|
|
}
|
|
|
|
func loadUserNets() ([]activeNet, error) {
|
|
files, err := listFiles(UserNetPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sort.Strings(files)
|
|
|
|
nets := make([]activeNet, 0, len(files))
|
|
|
|
for _, filename := range files {
|
|
filepath := path.Join(UserNetPath, filename)
|
|
|
|
if !strings.HasSuffix(filepath, ".conf") {
|
|
continue
|
|
}
|
|
|
|
n, err := loadNet(filepath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// "default" is slightly special
|
|
if n.conf.Name == "default" {
|
|
log.Printf(`Overriding "default" network with %v`, filename)
|
|
}
|
|
|
|
if netExists(nets, n.conf.Name) {
|
|
log.Printf("%q network already defined, ignoring %v", n.conf.Name, filename)
|
|
continue
|
|
}
|
|
|
|
nets = append(nets, *n)
|
|
}
|
|
|
|
return nets, nil
|
|
}
|