github.com/stackdocker/rkt@v0.10.1-0.20151109095037-1aa827478248/common/common.go (about)

     1  // Copyright 2014 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 common defines values shared by different parts
    16  // of rkt (e.g. stage0 and stage1)
    17  package common
    18  
    19  import (
    20  	"bufio"
    21  	"fmt"
    22  	"net"
    23  	"os"
    24  	"os/exec"
    25  	"path/filepath"
    26  	"strconv"
    27  	"strings"
    28  
    29  	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/aci"
    30  	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types"
    31  )
    32  
    33  const (
    34  	sharedVolumesDir = "/sharedVolumes"
    35  	stage1Dir        = "/stage1"
    36  	stage2Dir        = "/opt/stage2"
    37  	AppsInfoDir      = "/appsinfo"
    38  
    39  	EnvLockFd                    = "RKT_LOCK_FD"
    40  	EnvSELinuxContext            = "RKT_SELINUX_CONTEXT"
    41  	Stage1TreeStoreIDFilename    = "stage1TreeStoreID"
    42  	AppTreeStoreIDFilename       = "treeStoreID"
    43  	OverlayPreparedFilename      = "overlay-prepared"
    44  	PrivateUsersPreparedFilename = "private-users-prepared"
    45  
    46  	PrepareLock = "prepareLock"
    47  
    48  	MetadataServicePort    = 18112
    49  	MetadataServiceRegSock = "/run/rkt/metadata-svc.sock"
    50  
    51  	APIServiceListenClientURL = "localhost:15441"
    52  
    53  	DefaultLocalConfigDir  = "/etc/rkt"
    54  	DefaultSystemConfigDir = "/usr/lib/rkt"
    55  )
    56  
    57  // Stage1ImagePath returns the path where the stage1 app image (unpacked ACI) is rooted,
    58  // (i.e. where its contents are extracted during stage0).
    59  func Stage1ImagePath(root string) string {
    60  	return filepath.Join(root, stage1Dir)
    61  }
    62  
    63  // Stage1RootfsPath returns the path to the stage1 rootfs
    64  func Stage1RootfsPath(root string) string {
    65  	return filepath.Join(Stage1ImagePath(root), aci.RootfsDir)
    66  }
    67  
    68  // Stage1ManifestPath returns the path to the stage1's manifest file inside the expanded ACI.
    69  func Stage1ManifestPath(root string) string {
    70  	return filepath.Join(Stage1ImagePath(root), aci.ManifestFile)
    71  }
    72  
    73  // PodManifestPath returns the path in root to the Pod Manifest
    74  func PodManifestPath(root string) string {
    75  	return filepath.Join(root, "pod")
    76  }
    77  
    78  // AppsPath returns the path where the apps within a pod live.
    79  func AppsPath(root string) string {
    80  	return filepath.Join(Stage1RootfsPath(root), stage2Dir)
    81  }
    82  
    83  // AppPath returns the path to an app's rootfs.
    84  func AppPath(root string, appName types.ACName) string {
    85  	return filepath.Join(AppsPath(root), appName.String())
    86  }
    87  
    88  // AppRootfsPath returns the path to an app's rootfs.
    89  func AppRootfsPath(root string, appName types.ACName) string {
    90  	return filepath.Join(AppPath(root, appName), aci.RootfsDir)
    91  }
    92  
    93  // RelAppPath returns the path of an app relative to the stage1 chroot.
    94  func RelAppPath(appName types.ACName) string {
    95  	return filepath.Join(stage2Dir, appName.String())
    96  }
    97  
    98  // RelAppRootfsPath returns the path of an app's rootfs relative to the stage1 chroot.
    99  func RelAppRootfsPath(appName types.ACName) string {
   100  	return filepath.Join(RelAppPath(appName), aci.RootfsDir)
   101  }
   102  
   103  // ImageManifestPath returns the path to the app's manifest file of a pod.
   104  func ImageManifestPath(root string, appName types.ACName) string {
   105  	return filepath.Join(AppPath(root, appName), aci.ManifestFile)
   106  }
   107  
   108  // AppsInfoPath returns the path to the appsinfo directory of a pod.
   109  func AppsInfoPath(root string) string {
   110  	return filepath.Join(root, AppsInfoDir)
   111  }
   112  
   113  // AppInfoPath returns the path to the app's appsinfo directory of a pod.
   114  func AppInfoPath(root string, appName types.ACName) string {
   115  	return filepath.Join(AppsInfoPath(root), appName.String())
   116  }
   117  
   118  // AppTreeStoreIDPath returns the path to the app's treeStoreID file of a pod.
   119  func AppTreeStoreIDPath(root string, appName types.ACName) string {
   120  	return filepath.Join(AppInfoPath(root, appName), AppTreeStoreIDFilename)
   121  }
   122  
   123  // AppImageManifestPath returns the path to the app's ImageManifest file
   124  func AppInfoImageManifestPath(root string, appName types.ACName) string {
   125  	return filepath.Join(AppInfoPath(root, appName), aci.ManifestFile)
   126  }
   127  
   128  // SharedVolumesPath returns the path to the shared (empty) volumes of a pod.
   129  func SharedVolumesPath(root string) string {
   130  	return filepath.Join(root, sharedVolumesDir)
   131  }
   132  
   133  // MetadataServicePublicURL returns the public URL used to host the metadata service
   134  func MetadataServicePublicURL(ip net.IP, token string) string {
   135  	return fmt.Sprintf("http://%v:%v/%v", ip, MetadataServicePort, token)
   136  }
   137  
   138  func GetRktLockFD() (int, error) {
   139  	if v := os.Getenv(EnvLockFd); v != "" {
   140  		fd, err := strconv.ParseUint(v, 10, 32)
   141  		if err != nil {
   142  			return -1, err
   143  		}
   144  		return int(fd), nil
   145  	}
   146  	return -1, fmt.Errorf("%v env var is not set", EnvLockFd)
   147  }
   148  
   149  // SupportsOverlay returns whether the system supports overlay filesystem
   150  func SupportsOverlay() bool {
   151  	exec.Command("modprobe", "overlay").Run()
   152  
   153  	f, err := os.Open("/proc/filesystems")
   154  	if err != nil {
   155  		fmt.Println("error opening /proc/filesystems")
   156  		return false
   157  	}
   158  	defer f.Close()
   159  
   160  	s := bufio.NewScanner(f)
   161  	for s.Scan() {
   162  		if s.Text() == "nodev\toverlay" {
   163  			return true
   164  		}
   165  	}
   166  	return false
   167  }
   168  
   169  // SupportsUserNS returns whether the kernel has CONFIG_USER_NS set
   170  func SupportsUserNS() bool {
   171  	if _, err := os.Stat("/proc/self/uid_map"); err == nil {
   172  		return true
   173  	}
   174  
   175  	return false
   176  }
   177  
   178  // NetList implements the flag.Value interface to allow specification of --net with and without values
   179  // Example: --net="all,net1:k1=v1;k2=v2,net2:l1=w1"
   180  type NetList struct {
   181  	mapping map[string]string
   182  }
   183  
   184  func (l *NetList) String() string {
   185  	return strings.Join(l.Strings(), ",")
   186  }
   187  
   188  func (l *NetList) Set(value string) error {
   189  	if l.mapping == nil {
   190  		l.mapping = make(map[string]string)
   191  	}
   192  	for _, s := range strings.Split(value, ",") {
   193  		netArgsPair := strings.Split(s, ":")
   194  		netName := netArgsPair[0]
   195  
   196  		if netName == "" {
   197  			return fmt.Errorf("netname must not be empty")
   198  		}
   199  
   200  		if _, duplicate := l.mapping[netName]; duplicate {
   201  			return fmt.Errorf("found duplicate netname %q", netName)
   202  		}
   203  
   204  		switch {
   205  		case len(netArgsPair) == 1:
   206  			l.mapping[netName] = ""
   207  		case len(netArgsPair) == 2:
   208  			if netName == "all" ||
   209  				netName == "host" {
   210  				return fmt.Errorf("arguments are not supported by special netname %q", netName)
   211  			}
   212  			l.mapping[netName] = netArgsPair[1]
   213  		case len(netArgsPair) > 2:
   214  			return fmt.Errorf("network %q provided with invalid arguments: %v", netName, netArgsPair[1:])
   215  		default:
   216  			return fmt.Errorf("unexpected case when processing network %q", s)
   217  		}
   218  	}
   219  	return nil
   220  }
   221  
   222  func (l *NetList) Type() string {
   223  	return "netList"
   224  }
   225  
   226  func (l *NetList) Strings() []string {
   227  	if len(l.mapping) == 0 {
   228  		return []string{"default"}
   229  	}
   230  
   231  	var list []string
   232  	for k, v := range l.mapping {
   233  		if v == "" {
   234  			list = append(list, k)
   235  		} else {
   236  			list = append(list, fmt.Sprintf("%s:%s", k, v))
   237  		}
   238  	}
   239  	return list
   240  }
   241  
   242  func (l *NetList) StringsOnlyNames() []string {
   243  	var list []string
   244  	for k, _ := range l.mapping {
   245  		list = append(list, k)
   246  	}
   247  	return list
   248  }
   249  
   250  // Check if host networking has been requested
   251  func (l *NetList) Host() bool {
   252  	return l.Specific("host")
   253  }
   254  
   255  // Check if 'none' (loopback only) networking has been requested
   256  func (l *NetList) None() bool {
   257  	return l.Specific("none")
   258  }
   259  
   260  // Check if the container needs to be put in a separate network namespace
   261  func (l *NetList) Contained() bool {
   262  	return !l.Host() && len(l.mapping) > 0
   263  }
   264  
   265  func (l *NetList) Specific(net string) bool {
   266  	_, exists := l.mapping[net]
   267  	return exists
   268  }
   269  
   270  func (l *NetList) SpecificArgs(net string) string {
   271  	return l.mapping[net]
   272  }
   273  
   274  func (l *NetList) All() bool {
   275  	return l.Specific("all")
   276  }