net: stage1 gc will clean up networking

This commit is contained in:
Eugene Yakubovich
2015-04-14 15:35:08 -07:00
parent 98e78d5f08
commit bf33546a2d
10 changed files with 416 additions and 343 deletions
+2 -2
View File
@@ -51,7 +51,7 @@ After preparation completes, while still holding the exclusive lock (the lock is
`rkt run` transitions directly from #Prepare to #Run by renaming `$var/prepare/$uuid` to `$var/run/$uuid`, entirely skipping the #Prepared phase.
Should #Prepare fail or be interrupted, `$var/prepare/$uuid` will be left in an unlocked state. Any directory in `$var/prepare` in an unlocked state is considered a failed prepare. `rkt gc` identifies failed prepares in need of cleanup by trying to acquire a shared lock on all directories in `$var/prepare`, renaming successfully locked directories to `$var/garbage` where they are then deleted.
Should #Prepare fail or be interrupted, `$var/prepare/$uuid` will be left in an unlocked state. Any directory in `$var/prepare` in an unlocked state is considered a failed prepare. `rkt gc` identifies failed prepares in need of clean up by trying to acquire a shared lock on all directories in `$var/prepare`, renaming successfully locked directories to `$var/garbage` where they are then deleted.
## Prepared
@@ -91,7 +91,7 @@ Marked exited pods dwell in the `$var/exited-garbage` directory for a grace peri
A side-effect of the rename operation responsible for moving a pod from `$var/run` to `$var/exited-garbage` is an update to the pod directory's change time. The sweep operation takes advantage of this in honoring the necessary grace period before discarding exited pods. This grace period currently defaults to 30 minutes, and may be explicitly specified using the `--grace-period duration` flag with `rkt gc`. Note that this grace period begins from the time a pod was marked by `rkt gc`, not when the pod exited. A pod becomes eligible for marking upon exit, but will not become marked until a subsequent `rkt gc` is performed.
The change times of all directories found in `$var/exited-garbage` are compared against the current time. Directories having sufficiently old change times are locked exclusively and cleaned up. If a lock acquisition fails, the directory is skipped. Failed exclusive lock acquisitions may occur if the garbage pod is currently being accessed via `rkt status`, or deleted by a concurrent `rkt gc`, for example. The skipped pods will be revisited on a subsequent `rkt gc` invocation's sweep pass. During the cleanup, pod's stage1 gc entry point is first executed. This gives a stage1 to cleanup anything related to the environment shared between containers. Currently, this cleans up the private networking artifacts. After the completion of the gc entrypoint, the pod directory is recursively deleted.
The change times of all directories found in `$var/exited-garbage` are compared against the current time. Directories having sufficiently old change times are locked exclusively and cleaned up. If a lock acquisition fails, the directory is skipped. Failed exclusive lock acquisitions may occur if the garbage pod is currently being accessed via `rkt status`, or deleted by a concurrent `rkt gc`, for example. The skipped pods will be revisited on a subsequent `rkt gc` invocation's sweep pass. During the cleanup, the pod's stage1 gc entry point is first executed. This gives the stage1 a chance to clean up anything related to the environment shared between containers. The default stage1 uses the gc entrypoint to clean up the private networking artifacts. After the completion of the gc entrypoint, the pod directory is recursively deleted.
## Pulse
-122
View File
@@ -1,122 +0,0 @@
// Copyright 2015 CoreOS, Inc.
//
// 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 (
"fmt"
"io/ioutil"
"log"
"os"
"path"
"sort"
"github.com/coreos/rkt/common"
rktnet "github.com/coreos/rkt/networking/net"
)
// Net encodes a network plugin.
type Net struct {
rktnet.Net
args string
}
// Absolute path where users place their net configs
const UserNetPath = "/etc/rkt/net.d"
// Default net path relative to stage1 root
const DefaultNetPath = "etc/rkt/net.d/99-default.conf"
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 []Net, name string) bool {
for _, n := range nets {
if n.Name == name {
return true
}
}
return false
}
func loadUserNets() ([]Net, error) {
files, err := listFiles(UserNetPath)
if err != nil {
return nil, err
}
sort.Strings(files)
nets := make([]Net, 0, len(files))
for _, filename := range files {
filepath := path.Join(UserNetPath, filename)
n := Net{}
if err := rktnet.LoadNet(filepath, &n); err != nil {
return nil, fmt.Errorf("error loading %v: %v", filepath, err)
}
if n.Name == "default" {
log.Printf(`Overriding "default" network with %v`, filename)
}
if netExists(nets, n.Name) {
// "default" is slightly special
log.Printf("%q network already defined, ignoring %v", filename)
continue
}
nets = append(nets, n)
}
return nets, nil
}
// Loads nets specified by user and default one from stage1
func (e *podEnv) loadNets() ([]Net, error) {
nets, err := loadUserNets()
if err != nil {
return nil, err
}
if !netExists(nets, "default") {
defPath := path.Join(common.Stage1RootfsPath(e.rktRoot), DefaultNetPath)
defNet := Net{}
if err := rktnet.LoadNet(defPath, &defNet); err != nil {
return nil, fmt.Errorf("error loading net: %v", err)
}
nets = append(nets, defNet)
}
return nets, nil
}
+4 -23
View File
@@ -19,15 +19,13 @@ import (
"io/ioutil"
gonet "net"
"os"
"reflect"
)
// Net describes a network.
type Net struct {
Filename string
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
IPAM struct {
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
IPAM struct {
Type string `json:"type,omitempty"`
} `json:"ipam,omitempty"`
}
@@ -39,24 +37,7 @@ func LoadNet(path string, n interface{}) error {
return err
}
if err = json.Unmarshal(c, n); err != nil {
return err
}
// populate n.Filename if exists
v := reflect.ValueOf(n)
if v.Kind() == reflect.Ptr {
v = v.Elem()
if v.Kind() == reflect.Struct {
if fn := v.FieldByName("Filename"); fn.IsValid() {
if fn.Type().Kind() == reflect.String && fn.CanSet() {
fn.SetString(path)
}
}
}
}
return nil
return json.Unmarshal(c, n)
}
// this is what net plugin returns to rkt
+12 -12
View File
@@ -32,22 +32,22 @@ import (
const UserNetPluginsPath = "/usr/lib/rkt/plugins/net"
const BuiltinNetPluginsPath = "usr/lib/rkt/plugins/net"
func (e *podEnv) netPluginAdd(n *Net, netns, args, ifName string) (ip, hostIP net.IP, err error) {
output, err := e.execNetPlugin("ADD", n, netns, args, ifName)
func (e *podEnv) netPluginAdd(n *activeNet, netns string) (ip, hostIP net.IP, err error) {
output, err := e.execNetPlugin("ADD", n, netns)
if err != nil {
return nil, nil, err
}
ifConf := rktnet.IfConfig{}
if err = json.Unmarshal(output, &ifConf); err != nil {
return nil, nil, fmt.Errorf("error parsing %q output: %v", n.Name, err)
return nil, nil, fmt.Errorf("error parsing %q output: %v", n.Conf.Name, err)
}
return ifConf.IP, ifConf.HostIP, nil
}
func (e *podEnv) netPluginDel(n *Net, netns, args, ifName string) error {
_, err := e.execNetPlugin("DEL", n, netns, args, ifName)
func (e *podEnv) netPluginDel(n *activeNet, netns string) error {
_, err := e.execNetPlugin("DEL", n, netns)
return err
}
@@ -80,20 +80,20 @@ func envVars(vars [][2]string) []string {
return env
}
func (e *podEnv) execNetPlugin(cmd string, n *Net, netns, args, ifName string) ([]byte, error) {
pluginPath := e.findNetPlugin(n.Type)
func (e *podEnv) execNetPlugin(cmd string, n *activeNet, netns string) ([]byte, error) {
pluginPath := e.findNetPlugin(n.Conf.Type)
if pluginPath == "" {
return nil, fmt.Errorf("Could not find plugin %q", n.Type)
return nil, fmt.Errorf("Could not find plugin %q", n.Conf.Type)
}
vars := [][2]string{
{"RKT_NETPLUGIN_COMMAND", cmd},
{"RKT_NETPLUGIN_PODID", e.podID.String()},
{"RKT_NETPLUGIN_NETNS", netns},
{"RKT_NETPLUGIN_ARGS", args},
{"RKT_NETPLUGIN_IFNAME", ifName},
{"RKT_NETPLUGIN_NETNAME", n.Name},
{"RKT_NETPLUGIN_NETCONF", n.Filename},
{"RKT_NETPLUGIN_ARGS", n.Runtime.Args},
{"RKT_NETPLUGIN_IFNAME", n.Runtime.IfName},
{"RKT_NETPLUGIN_NETNAME", n.Conf.Name},
{"RKT_NETPLUGIN_NETCONF", n.Runtime.ConfPath},
{"RKT_NETPLUGIN_IPAMPATH", strings.Join(e.pluginPaths(), ":")},
}
+6 -3
View File
@@ -16,6 +16,7 @@ package netinfo
import (
"encoding/json"
"net"
"os"
"path/filepath"
"syscall"
@@ -24,9 +25,11 @@ import (
const filename = "net-info.json"
type NetInfo struct {
NetName string `json:"netName"`
IfName string `json:"ifName"`
IP string `json:"ip"`
NetName string `json:"netName"`
ConfPath string `json:"netConf"`
IfName string `json:"ifName"`
IP net.IP `json:"ip"`
Args string `json:"args"`
}
func LoadAt(cdirfd int) ([]NetInfo, error) {
+101 -167
View File
@@ -16,16 +16,15 @@ package networking
import (
"fmt"
"io"
"log"
"net"
"os"
"path/filepath"
"syscall"
"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types"
"github.com/coreos/rkt/Godeps/_workspace/src/github.com/vishvananda/netlink"
rktnet "github.com/coreos/rkt/networking/net"
"github.com/coreos/rkt/networking/netinfo"
"github.com/coreos/rkt/networking/util"
)
@@ -35,21 +34,6 @@ const (
selfNetNS = "/proc/self/ns/net"
)
type activeNet struct {
Net
ifName string
ip net.IP
hostIP net.IP // kludge for default network
}
// "base" struct that's populated from the beginning
// describing the environment in which the pod
// is running in
type podEnv struct {
rktRoot string
podID types.UUID
}
// ForwardedPort describes a port that will be
// forwarded (mapped) from the host to the pod
type ForwardedPort struct {
@@ -62,19 +46,14 @@ type ForwardedPort struct {
type Networking struct {
podEnv
MetadataIP net.IP
HostIP net.IP
podID types.UUID
hostNS *os.File
podNS *os.File
podNSPath string
nets []activeNet
hostNS *os.File
nets []activeNet
}
// Setup produces a Networking object for a given pod ID.
// Setup creates a new networking namespace and executes network
// plugins to setup private networking. It returns in the new pod
// namespace
func Setup(rktRoot string, podID types.UUID, fps []ForwardedPort) (*Networking, error) {
var err error
n := Networking{
podEnv: podEnv{
rktRoot: rktRoot,
@@ -82,69 +61,115 @@ func Setup(rktRoot string, podID types.UUID, fps []ForwardedPort) (*Networking,
},
}
defer func() {
// cleanup on error
if err != nil {
n.Teardown()
}
}()
if n.hostNS, n.podNS, err = basicNetNS(); err != nil {
hostNS, podNS, err := basicNetNS()
if err != nil {
return nil, err
}
// we're in podNS!
n.hostNS = hostNS
n.podNSPath = filepath.Join(rktRoot, "netns")
if err = bindMountFile(selfNetNS, n.podNSPath); err != nil {
nspath := n.podNSPath()
if err = bindMountFile(selfNetNS, nspath); err != nil {
return nil, err
}
nets, err := n.loadNets()
defer func() {
if err != nil {
if err := syscall.Unmount(nspath, 0); err != nil {
log.Printf("Error unmounting %q: %v", nspath, err)
}
}
}()
n.nets, err = n.loadNets()
if err != nil {
return nil, fmt.Errorf("error loading network definitions: %v", err)
}
err = withNetNS(n.podNS, n.hostNS, func() error {
n.nets, err = n.setupNets(n.podNSPath, nets)
if err != nil {
err = withNetNS(podNS, hostNS, func() error {
if err := n.setupNets(n.nets); err != nil {
return err
}
if len(n.nets) == 0 {
return fmt.Errorf("no nets successfully configured")
}
// last net is the default
n.MetadataIP = n.nets[len(n.nets)-1].ip
n.HostIP = n.nets[len(n.nets)-1].hostIP
return n.forwardPorts(fps, n.MetadataIP)
return n.forwardPorts(fps, n.GetDefaultIP())
})
if err != nil {
return nil, err
}
if err = n.saveNetInfo(); err != nil {
return nil, err
}
return &n, nil
}
// Load creates the Networking object from saved state.
// Assumes the current netns is that of the host.
func Load(rktRoot string, podID *types.UUID) (*Networking, error) {
// the current directory is pod root
pdirfd, err := syscall.Open(rktRoot, syscall.O_RDONLY|syscall.O_DIRECTORY, 0)
if err != nil {
return nil, fmt.Errorf("Failed to open pod root directory (%v): %v", rktRoot, err)
}
defer syscall.Close(pdirfd)
nis, err := netinfo.LoadAt(pdirfd)
if err != nil {
return nil, err
}
hostNS, err := os.Open(selfNetNS)
if err != nil {
return nil, err
}
nets := []activeNet{}
for _, ni := range nis {
conf := &rktnet.Net{}
if err := rktnet.LoadNet(ni.ConfPath, conf); err != nil {
if !os.IsNotExist(err) {
log.Printf("Error loading %q: %v; ignoring", ni.ConfPath, err)
}
continue
}
// make a copy of ni to make it a unique object as it's saved via ptr
rti := ni
nets = append(nets, activeNet{
Conf: conf,
Runtime: &rti,
})
}
return &Networking{
podEnv: podEnv{
rktRoot: rktRoot,
podID: *podID,
},
hostNS: hostNS,
nets: nets,
}, nil
}
func (n *Networking) GetDefaultIP() net.IP {
if len(n.nets) == 0 {
return nil
}
return n.nets[len(n.nets)-1].Runtime.IP
}
func (n *Networking) GetDefaultHostIP() net.IP {
if len(n.nets) == 0 {
return nil
}
return n.nets[len(n.nets)-1].hostIP
}
// Teardown cleans up a produced Networking object.
func (n *Networking) Teardown() {
// Teardown everything in reverse order of setup.
// This is called during error cases as well, so
// not everything may be setup.
// N.B. better to keep going in case of errors
// to get as much cleaned up as possible.
// This should be indempotent -- be tolerant of
// missing stuff
if n.podNS == nil || n.hostNS == nil {
return
}
if err := n.EnterHostNS(); err != nil {
log.Print(err)
if err := n.enterHostNS(); err != nil {
log.Printf("Error switching to host netns: %v", err)
return
}
@@ -152,14 +177,13 @@ func (n *Networking) Teardown() {
log.Printf("Error removing forwarded ports: %v", err)
}
n.teardownNets(n.podNSPath, n.nets)
n.teardownNets(n.nets)
if n.podNSPath == "" {
return
}
if err := syscall.Unmount(n.podNSPath, 0); err != nil {
log.Printf("Error unmounting %q: %v", n.podNSPath, err)
if err := syscall.Unmount(n.podNSPath(), 0); err != nil {
// if already unmounted, umount(2) returns EINVAL
if !os.IsNotExist(err) && err != syscall.EINVAL {
log.Printf("Error unmounting %q: %v", n.podNSPath(), err)
}
}
}
@@ -181,88 +205,17 @@ func basicNetNS() (hostNS, podNS *os.File, err error) {
return
}
// EnterHostNS moves into the host's network namespace.
func (n *Networking) EnterHostNS() error {
// enterHostNS moves into the host's network namespace.
func (n *Networking) enterHostNS() error {
return util.SetNS(n.hostNS, syscall.CLONE_NEWNET)
}
// EnterPodNS moves into the pod's network namespace.
func (n *Networking) EnterPodNS() error {
return util.SetNS(n.podNS, syscall.CLONE_NEWNET)
}
func (e *podEnv) netDir() string {
return filepath.Join(e.rktRoot, "net")
}
func (e *podEnv) setupNets(netns string, nets []Net) ([]activeNet, error) {
err := os.MkdirAll(e.netDir(), 0755)
if err != nil {
return nil, err
}
active := []activeNet{}
for i, nt := range nets {
log.Printf("Setup: executing net-plugin %v", nt.Type)
an := activeNet{
Net: nt,
ifName: fmt.Sprintf(ifnamePattern, i),
}
if an.Filename, err = copyFileToDir(nt.Filename, e.netDir()); err != nil {
err = fmt.Errorf("error copying %q to %q: %v", nt.Filename, e.netDir(), err)
break
}
an.ip, an.hostIP, err = e.netPluginAdd(&nt, netns, nt.args, an.ifName)
if err != nil {
err = fmt.Errorf("error adding network %q: %v", nt.Name, err)
break
}
active = append(active, an)
}
if err != nil {
e.teardownNets(netns, active)
return nil, err
}
return active, nil
}
func (e *podEnv) teardownNets(netns string, nets []activeNet) {
for i := len(nets) - 1; i >= 0; i-- {
nt := nets[i]
log.Printf("Teardown: executing net-plugin %v", nt.Type)
err := e.netPluginDel(&nt.Net, netns, nt.args, nt.ifName)
if err != nil {
log.Printf("Error deleting %q: %v", nt.Name, err)
}
// Delete the conf file to signal that the network was
// torn down (or at least attempted to)
if err = os.Remove(nt.Filename); err != nil {
log.Printf("Error deleting %q: %v", nt.Filename, err)
}
}
}
// saveNetInfo writes out the info about active nets
// Save writes out the info about active nets
// for "rkt list" and friends to display
func (e *Networking) saveNetInfo() error {
func (e *Networking) Save() error {
nis := []netinfo.NetInfo{}
for _, n := range e.nets {
ni := netinfo.NetInfo{
NetName: n.Name,
IfName: n.ifName,
IP: n.ip.String(),
}
nis = append(nis, ni)
nis = append(nis, *n.Runtime)
}
return netinfo.Save(e.rktRoot, nis)
@@ -338,22 +291,3 @@ func bindMountFile(src, dst string) error {
return syscall.Mount(src, dst, "none", syscall.MS_BIND, "")
}
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
}
+232
View File
@@ -0,0 +1,232 @@
// Copyright 2015 CoreOS, Inc.
//
// 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 (
"fmt"
"io"
"io/ioutil"
"log"
"net"
"os"
"path"
"path/filepath"
"sort"
"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types"
"github.com/coreos/rkt/common"
rktnet "github.com/coreos/rkt/networking/net"
"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 {
rktRoot string
podID types.UUID
}
type activeNet struct {
Conf *rktnet.Net
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.rktRoot), 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.rktRoot, "netns")
}
func (e *podEnv) netDir() string {
return filepath.Join(e.rktRoot, "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) {
n := &rktnet.Net{}
if err := rktnet.LoadNet(filepath, n); err != nil {
return nil, fmt.Errorf("error loading %v: %v", filepath, err)
}
return &activeNet{
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)
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
}
+2 -7
View File
@@ -1,4 +1,4 @@
// Copyright 2014 CoreOS, Inc.
// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
package stage0
import (
"fmt"
"log"
"os"
"os/exec"
@@ -48,9 +47,5 @@ func GC(pdir string, uuid *types.UUID, debug bool) error {
Stderr: os.Stderr,
Dir: pdir,
}
if err := c.Run(); err != nil {
return fmt.Errorf("error running gc: %v", err)
}
return nil
return c.Run()
}
+52 -2
View File
@@ -17,10 +17,60 @@
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"runtime"
"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types"
"github.com/coreos/rkt/networking"
)
func main() {
fmt.Fprintln(os.Stderr, "Hello from stage1 GC")
var (
debug bool
)
func init() {
flag.BoolVar(&debug, "debug", false, "Run in debug mode")
// this ensures that main runs only on main thread (thread group leader).
// since namespace ops (unshare, setns) are done for a single thread, we
// must ensure that the goroutine does not jump from OS thread to thread
runtime.LockOSThread()
}
func main() {
flag.Parse()
if !debug {
log.SetOutput(ioutil.Discard)
}
podID, err := types.NewUUID(flag.Arg(0))
if err != nil {
fmt.Fprintln(os.Stderr, "UUID is missing or malformed")
os.Exit(1)
}
if err := gcNetworking(podID); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func gcNetworking(podID *types.UUID) error {
n, err := networking.Load(".", podID)
switch {
case err == nil:
n.Teardown()
case os.IsNotExist(err):
// probably ran without --private-net
default:
return fmt.Errorf("Failed loading networking state: %v", err)
}
return nil
}
+5 -5
View File
@@ -236,14 +236,14 @@ func stage1() int {
}
defer n.Teardown()
p.MetadataServiceURL = common.MetadataServicePublicURL(n.HostIP)
if err = n.EnterPodNS(); err != nil {
fmt.Fprintf(os.Stderr, "Failed to switch to pod netns: %v\n", err)
if err = n.Save(); err != nil {
fmt.Fprintf(os.Stderr, "Failed to save networking state %v\n", err)
return 6
}
if err = registerPod(p, n.MetadataIP); err != nil {
p.MetadataServiceURL = common.MetadataServicePublicURL(n.GetDefaultHostIP())
if err = registerPod(p, n.GetDefaultIP()); err != nil {
fmt.Fprintf(os.Stderr, "Failed to register pod: %v\n", err)
return 6
}