github.com/stackdocker/rkt@v0.10.1-0.20151109095037-1aa827478248/rkt/prepare.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 //+build linux 16 17 package main 18 19 import ( 20 "os" 21 22 "github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types" 23 "github.com/coreos/rkt/Godeps/_workspace/src/github.com/spf13/cobra" 24 "github.com/coreos/rkt/common" 25 "github.com/coreos/rkt/pkg/lock" 26 "github.com/coreos/rkt/pkg/uid" 27 "github.com/coreos/rkt/stage0" 28 "github.com/coreos/rkt/store" 29 ) 30 31 var ( 32 cmdPrepare = &cobra.Command{ 33 Use: "prepare [--volume=name,kind=host,...] [--mount volume=VOL,target=PATH] [--quiet] IMAGE [-- image-args...[---]]...", 34 Short: "Prepare to run image(s) in a pod in rkt", 35 Long: `IMAGE should be a string referencing an image; either a hash, local file on disk, or URL. 36 They will be checked in that order and the first match will be used. 37 38 An "--" may be used to inhibit rkt prepare's parsing of subsequent arguments, 39 which will instead be appended to the preceding image app's exec arguments. 40 End the image arguments with a lone "---" to resume argument parsing.`, 41 Run: runWrapper(runPrepare), 42 } 43 flagQuiet bool 44 ) 45 46 func init() { 47 cmdRkt.AddCommand(cmdPrepare) 48 49 addStage1ImageFlag(cmdPrepare.Flags()) 50 cmdPrepare.Flags().Var(&flagPorts, "port", "ports to expose on the host (needs contained networking with NAT)") 51 cmdPrepare.Flags().BoolVar(&flagQuiet, "quiet", false, "suppress superfluous output on stdout, print only the UUID on success") 52 cmdPrepare.Flags().BoolVar(&flagInheritEnv, "inherit-env", false, "inherit all environment variables not set by apps") 53 cmdPrepare.Flags().BoolVar(&flagNoOverlay, "no-overlay", false, "disable overlay filesystem") 54 cmdPrepare.Flags().BoolVar(&flagPrivateUsers, "private-users", false, "run within user namespaces (experimental).") 55 cmdPrepare.Flags().Var(&flagExplicitEnv, "set-env", "an environment variable to set for apps in the form name=value") 56 cmdPrepare.Flags().BoolVar(&flagStoreOnly, "store-only", false, "use only available images in the store (do not discover or download from remote URLs)") 57 cmdPrepare.Flags().BoolVar(&flagNoStore, "no-store", false, "fetch images ignoring the local store") 58 cmdPrepare.Flags().StringVar(&flagPodManifest, "pod-manifest", "", "the path to the pod manifest. If it's non-empty, then only '--quiet' and '--no-overlay' will have effects") 59 cmdPrepare.Flags().Var((*appsVolume)(&rktApps), "volume", "volumes to make available in the pod") 60 61 // per-app flags 62 cmdPrepare.Flags().Var((*appExec)(&rktApps), "exec", "override the exec command for the preceding image") 63 cmdPrepare.Flags().Var((*appMount)(&rktApps), "mount", "mount point binding a volume to a path within an app") 64 65 // Disable interspersed flags to stop parsing after the first non flag 66 // argument. This is need to permit to correctly handle 67 // multiple "IMAGE -- imageargs ---" options 68 cmdPrepare.Flags().SetInterspersed(false) 69 } 70 71 func runPrepare(cmd *cobra.Command, args []string) (exit int) { 72 var err error 73 origStdout := os.Stdout 74 privateUsers := uid.NewBlankUidRange() 75 if flagQuiet { 76 if os.Stdout, err = os.Open("/dev/null"); err != nil { 77 stderr("prepare: unable to open /dev/null: %v", err) 78 return 1 79 } 80 } 81 82 if flagStoreOnly && flagNoStore { 83 stderr("both --store-only and --no-store specified") 84 return 1 85 } 86 87 if flagPrivateUsers { 88 if !common.SupportsUserNS() { 89 stderr("prepare: --private-users is not supported, kernel compiled without user namespace support") 90 return 1 91 } 92 privateUsers.SetRandomUidRange(uid.DefaultRangeCount) 93 } 94 95 if err = parseApps(&rktApps, args, cmd.Flags(), true); err != nil { 96 stderr("prepare: error parsing app image arguments: %v", err) 97 return 1 98 } 99 100 if len(flagPodManifest) > 0 && (len(flagPorts) > 0 || flagInheritEnv || !flagExplicitEnv.IsEmpty() || flagStoreOnly || flagNoStore) { 101 stderr("prepare: conflicting flags set with --pod-manifest (see --help)") 102 return 1 103 } 104 105 if rktApps.Count() < 1 && len(flagPodManifest) == 0 { 106 stderr("prepare: must provide at least one image or specify the pod manifest") 107 return 1 108 } 109 110 s, err := store.NewStore(globalFlags.Dir) 111 if err != nil { 112 stderr("prepare: cannot open store: %v", err) 113 return 1 114 } 115 116 config, err := getConfig() 117 if err != nil { 118 stderr("prepare: cannot get configuration: %v", err) 119 return 1 120 } 121 fn := &finder{ 122 imageActionData: imageActionData{ 123 s: s, 124 headers: config.AuthPerHost, 125 dockerAuth: config.DockerCredentialsPerRegistry, 126 insecureSkipVerify: globalFlags.InsecureSkipVerify, 127 debug: globalFlags.Debug, 128 }, 129 storeOnly: flagStoreOnly, 130 noStore: flagNoStore, 131 withDeps: false, 132 } 133 134 s1img, err := getStage1Hash(s, cmd) 135 if err != nil { 136 stderr("prepare: %v", err) 137 return 1 138 } 139 140 fn.ks = getKeystore() 141 fn.withDeps = true 142 if err := fn.findImages(&rktApps); err != nil { 143 stderr("prepare: %v", err) 144 return 1 145 } 146 147 p, err := newPod() 148 if err != nil { 149 stderr("prepare: error creating new pod: %v", err) 150 return 1 151 } 152 153 cfg := stage0.CommonConfig{ 154 Store: s, 155 Stage1Image: *s1img, 156 UUID: p.uuid, 157 Debug: globalFlags.Debug, 158 } 159 160 pcfg := stage0.PrepareConfig{ 161 CommonConfig: cfg, 162 UseOverlay: !flagNoOverlay && common.SupportsOverlay(), 163 PrivateUsers: privateUsers, 164 } 165 166 if len(flagPodManifest) > 0 { 167 pcfg.PodManifest = flagPodManifest 168 } else { 169 pcfg.Ports = []types.ExposedPort(flagPorts) 170 pcfg.InheritEnv = flagInheritEnv 171 pcfg.ExplicitEnv = flagExplicitEnv.Strings() 172 pcfg.Apps = &rktApps 173 } 174 175 if globalFlags.Debug { 176 stage0.InitDebug() 177 } 178 179 keyLock, err := lock.SharedKeyLock(lockDir(), common.PrepareLock) 180 if err != nil { 181 stderr("rkt: cannot get shared prepare lock: %v", err) 182 return 1 183 } 184 if err = stage0.Prepare(pcfg, p.path(), p.uuid); err != nil { 185 stderr("prepare: error setting up stage0: %v", err) 186 keyLock.Close() 187 return 1 188 } 189 keyLock.Close() 190 191 if err := p.sync(); err != nil { 192 stderr("prepare: error syncing pod data: %v", err) 193 return 1 194 } 195 196 if err := p.xToPrepared(); err != nil { 197 stderr("prepare: error transitioning to prepared: %v", err) 198 return 1 199 } 200 201 os.Stdout = origStdout // restore output in case of --quiet 202 stdout("%s", p.uuid.String()) 203 204 return 0 205 }