github.com/schwarzm/garden-linux@v0.0.0-20150507151835-33bca2147c47/old/main.go (about) 1 package old 2 3 import ( 4 "bytes" 5 "flag" 6 "fmt" 7 "net" 8 "os" 9 "os/exec" 10 "os/signal" 11 "runtime" 12 "strings" 13 "syscall" 14 15 "github.com/cloudfoundry/gunk/command_runner" 16 "github.com/cloudfoundry/gunk/localip" 17 "github.com/docker/docker/daemon/graphdriver" 18 _ "github.com/docker/docker/daemon/graphdriver/aufs" 19 _ "github.com/docker/docker/daemon/graphdriver/vfs" 20 "github.com/docker/docker/graph" 21 "github.com/docker/docker/registry" 22 "github.com/pivotal-golang/clock" 23 "github.com/pivotal-golang/lager" 24 25 "github.com/cloudfoundry-incubator/cf-debug-server" 26 "github.com/cloudfoundry-incubator/cf-lager" 27 "github.com/cloudfoundry-incubator/garden-linux/container_pool" 28 "github.com/cloudfoundry-incubator/garden-linux/container_repository" 29 "github.com/cloudfoundry-incubator/garden-linux/linux_backend" 30 "github.com/cloudfoundry-incubator/garden-linux/network" 31 "github.com/cloudfoundry-incubator/garden-linux/network/bridgemgr" 32 "github.com/cloudfoundry-incubator/garden-linux/network/devices" 33 "github.com/cloudfoundry-incubator/garden-linux/network/iptables" 34 "github.com/cloudfoundry-incubator/garden-linux/network/subnets" 35 "github.com/cloudfoundry-incubator/garden-linux/old/port_pool" 36 "github.com/cloudfoundry-incubator/garden-linux/old/quota_manager" 37 "github.com/cloudfoundry-incubator/garden-linux/old/repository_fetcher" 38 "github.com/cloudfoundry-incubator/garden-linux/old/rootfs_provider" 39 "github.com/cloudfoundry-incubator/garden-linux/old/sysconfig" 40 "github.com/cloudfoundry-incubator/garden-linux/old/system_info" 41 "github.com/cloudfoundry-incubator/garden/server" 42 "github.com/cloudfoundry/dropsonde" 43 "github.com/cloudfoundry/gunk/command_runner/linux_command_runner" 44 ) 45 46 const ( 47 DefaultNetworkPool = "10.254.0.0/22" 48 DefaultMTUSize = 1500 49 ) 50 51 var listenNetwork = flag.String( 52 "listenNetwork", 53 "unix", 54 "how to listen on the address (unix, tcp, etc.)", 55 ) 56 57 var listenAddr = flag.String( 58 "listenAddr", 59 "/tmp/garden.sock", 60 "address to listen on", 61 ) 62 63 var snapshotsPath = flag.String( 64 "snapshots", 65 "", 66 "directory in which to store container state to persist through restarts", 67 ) 68 69 var binPath = flag.String( 70 "bin", 71 "", 72 "directory containing backend-specific scripts (i.e. ./create.sh)", 73 ) 74 75 var depotPath = flag.String( 76 "depot", 77 "", 78 "directory in which to store containers", 79 ) 80 81 var overlaysPath = flag.String( 82 "overlays", 83 "", 84 "directory in which to store containers mount points", 85 ) 86 87 var rootFSPath = flag.String( 88 "rootfs", 89 "", 90 "directory of the rootfs for the containers", 91 ) 92 93 var disableQuotas = flag.Bool( 94 "disableQuotas", 95 false, 96 "disable disk quotas", 97 ) 98 99 var containerGraceTime = flag.Duration( 100 "containerGraceTime", 101 0, 102 "time after which to destroy idle containers", 103 ) 104 105 var portPoolStart = flag.Uint( 106 "portPoolStart", 107 61001, 108 "start of ephemeral port range used for mapped container ports", 109 ) 110 111 var portPoolSize = flag.Uint( 112 "portPoolSize", 113 5000, 114 "size of port pool used for mapped container ports", 115 ) 116 117 var uidMappingOffset = flag.Int( 118 "uidMappingOffset", 119 600000, 120 "start of mapped UID range for unprivileged containers (the root user in an unprivileged container will have this host uid)", 121 ) 122 123 var networkPool = flag.String("networkPool", 124 DefaultNetworkPool, 125 "Pool of dynamically allocated container subnets") 126 127 var denyNetworks = flag.String( 128 "denyNetworks", 129 "", 130 "CIDR blocks representing IPs to blacklist", 131 ) 132 133 var allowNetworks = flag.String( 134 "allowNetworks", 135 "", 136 "CIDR blocks representing IPs to whitelist", 137 ) 138 139 var graphRoot = flag.String( 140 "graph", 141 "/var/lib/garden-docker-graph", 142 "docker image graph", 143 ) 144 145 var dockerRegistry = flag.String( 146 "registry", 147 registry.IndexServerAddress(), 148 "docker registry API endpoint", 149 ) 150 151 var insecureRegistries = flag.String( 152 "insecureDockerRegistryList", 153 "", 154 "comma-separated list of docker registries to allow connection to even if they are not secure", 155 ) 156 157 var tag = flag.String( 158 "tag", 159 "", 160 "server-wide identifier used for 'global' configuration, must be less than 3 character long", 161 ) 162 163 var dropsondeOrigin = flag.String( 164 "dropsondeOrigin", 165 "garden-linux", 166 "Origin identifier for dropsonde-emitted metrics.", 167 ) 168 169 var dropsondeDestination = flag.String( 170 "dropsondeDestination", 171 "localhost:3457", 172 "Destination for dropsonde-emitted metrics.", 173 ) 174 175 var allowHostAccess = flag.Bool( 176 "allowHostAccess", 177 false, 178 "allow network access to host", 179 ) 180 181 var iptablesLogMethod = flag.String( 182 "iptablesLogMethod", 183 "kernel", 184 "type of iptable logging to use, one of 'kernel' or 'nflog' (default: kernel)", 185 ) 186 187 var mtu = flag.Int( 188 "mtu", 189 DefaultMTUSize, 190 "MTU size for container network interfaces") 191 192 var externalIP = flag.String( 193 "externalIP", 194 "", 195 "IP address to use to reach container's mapped ports") 196 197 func Main() { 198 199 cf_debug_server.AddFlags(flag.CommandLine) 200 cf_lager.AddFlags(flag.CommandLine) 201 flag.Parse() 202 203 runtime.GOMAXPROCS(runtime.NumCPU()) 204 205 logger, reconfigurableSink := cf_lager.New("garden-linux") 206 if dbgAddr := cf_debug_server.DebugAddress(flag.CommandLine); dbgAddr != "" { 207 cf_debug_server.Run(dbgAddr, reconfigurableSink) 208 } 209 210 initializeDropsonde(logger) 211 212 if *binPath == "" { 213 missing("-bin") 214 } 215 216 if *depotPath == "" { 217 missing("-depot") 218 } 219 220 if *overlaysPath == "" { 221 missing("-overlays") 222 } 223 224 if len(*tag) > 2 { 225 println("-tag parameter must be less than 3 characters long") 226 println() 227 flag.Usage() 228 return 229 } 230 231 _, dynamicRange, _ := net.ParseCIDR(*networkPool) 232 subnetPool, _ := subnets.NewSubnets(dynamicRange) 233 234 // TODO: use /proc/sys/net/ipv4/ip_local_port_range by default (end + 1) 235 portPool := port_pool.New(uint32(*portPoolStart), uint32(*portPoolSize)) 236 237 useKernelLogging := true 238 switch *iptablesLogMethod { 239 case "nflog": 240 useKernelLogging = false 241 case "kernel": 242 /* noop */ 243 default: 244 println("-iptablesLogMethod value not recognized") 245 println() 246 flag.Usage() 247 return 248 } 249 250 config := sysconfig.NewConfig(*tag, *allowHostAccess) 251 252 runner := sysconfig.NewRunner(config, linux_command_runner.New()) 253 254 quotaManager := quota_manager.New(runner, getMountPoint(logger, *depotPath), *binPath) 255 256 if *disableQuotas { 257 quotaManager.Disable() 258 } 259 260 if err := os.MkdirAll(*graphRoot, 0755); err != nil { 261 logger.Fatal("failed-to-create-graph-directory", err) 262 } 263 264 graphDriver, err := graphdriver.New(*graphRoot, nil) 265 if err != nil { 266 logger.Fatal("failed-to-construct-graph-driver", err) 267 } 268 269 graph, err := graph.NewGraph(*graphRoot, graphDriver) 270 if err != nil { 271 logger.Fatal("failed-to-construct-graph", err) 272 } 273 274 repoFetcher := repository_fetcher.Retryable{ 275 repository_fetcher.New( 276 repository_fetcher.NewRepositoryProvider( 277 *dockerRegistry, 278 strings.Split(*insecureRegistries, ","), 279 ), 280 graph, 281 ), 282 } 283 284 uidMappings := rootfs_provider.MappingList{{ 285 FromID: 0, 286 ToID: *uidMappingOffset, 287 Size: 65534, // map an almost-16-bit range 288 }} 289 290 rootFSNamespacer := &rootfs_provider.UidNamespacer{ 291 Logger: logger, 292 Translator: rootfs_provider.NewUidTranslator( 293 uidMappings, 294 uidMappings, 295 ).Translate, 296 } 297 298 copier := &rootfs_provider.ShellOutCp{} 299 dockerRootFSProvider, err := rootfs_provider.NewDocker(repoFetcher, graphDriver, rootfs_provider.SimpleVolumeCreator{}, rootFSNamespacer, copier, clock.NewClock()) 300 if err != nil { 301 logger.Fatal("failed-to-construct-docker-rootfs-provider", err) 302 } 303 304 rootFSProviders := map[string]rootfs_provider.RootFSProvider{ 305 "": rootfs_provider.NewOverlay(*binPath, *overlaysPath, *rootFSPath, runner), 306 "docker": dockerRootFSProvider, 307 } 308 309 filterProvider := &provider{ 310 useKernelLogging: useKernelLogging, 311 chainPrefix: config.IPTables.Filter.InstancePrefix, 312 runner: runner, 313 log: logger, 314 } 315 316 if *externalIP == "" { 317 ip, err := localip.LocalIP() 318 if err != nil { 319 panic("couldn't determine local IP to use for -externalIP parameter. You can use the -externalIP flag to pass an external IP") 320 } 321 322 externalIP = &ip 323 } 324 325 parsedExternalIP := net.ParseIP(*externalIP) 326 if parsedExternalIP == nil { 327 panic(fmt.Sprintf("Value of -externalIP %s could not be converted to an IP", *externalIP)) 328 } 329 330 pool := container_pool.New( 331 logger, 332 *binPath, 333 *depotPath, 334 config, 335 rootFSProviders, 336 *uidMappingOffset, 337 parsedExternalIP, 338 *mtu, 339 subnetPool, 340 bridgemgr.New("w"+config.Tag+"b-", &devices.Bridge{}, &devices.Link{}), 341 filterProvider, 342 iptables.NewGlobalChain(config.IPTables.Filter.DefaultChain, runner, logger.Session("global-chain")), 343 portPool, 344 strings.Split(*denyNetworks, ","), 345 strings.Split(*allowNetworks, ","), 346 runner, 347 quotaManager, 348 ) 349 350 systemInfo := system_info.NewProvider(*depotPath) 351 352 backend := linux_backend.New(logger, pool, container_repository.New(), systemInfo, *snapshotsPath) 353 354 err = backend.Setup() 355 if err != nil { 356 logger.Fatal("failed-to-set-up-backend", err) 357 } 358 359 graceTime := *containerGraceTime 360 361 gardenServer := server.New(*listenNetwork, *listenAddr, graceTime, backend, logger) 362 363 err = gardenServer.Start() 364 if err != nil { 365 logger.Fatal("failed-to-start-server", err) 366 } 367 368 signals := make(chan os.Signal, 1) 369 370 go func() { 371 <-signals 372 gardenServer.Stop() 373 os.Exit(0) 374 }() 375 376 signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP) 377 378 logger.Info("started", lager.Data{ 379 "network": *listenNetwork, 380 "addr": *listenAddr, 381 }) 382 383 select {} 384 } 385 386 func getMountPoint(logger lager.Logger, depotPath string) string { 387 dfOut := new(bytes.Buffer) 388 389 df := exec.Command("df", depotPath) 390 df.Stdout = dfOut 391 df.Stderr = os.Stderr 392 393 err := df.Run() 394 if err != nil { 395 logger.Fatal("failed-to-get-mount-info", err) 396 } 397 398 dfOutputWords := strings.Split(string(dfOut.Bytes()), " ") 399 400 return strings.Trim(dfOutputWords[len(dfOutputWords)-1], "\n") 401 } 402 403 func missing(flagName string) { 404 println("missing " + flagName) 405 println() 406 flag.Usage() 407 } 408 409 func initializeDropsonde(logger lager.Logger) { 410 err := dropsonde.Initialize(*dropsondeDestination, *dropsondeOrigin) 411 if err != nil { 412 logger.Error("failed to initialize dropsonde: %v", err) 413 } 414 } 415 416 type provider struct { 417 useKernelLogging bool 418 chainPrefix string 419 runner command_runner.CommandRunner 420 log lager.Logger 421 } 422 423 func (p *provider) ProvideFilter(containerId string) network.Filter { 424 return network.NewFilter(iptables.NewLoggingChain(p.chainPrefix+containerId, p.useKernelLogging, p.runner, p.log.Session(containerId).Session("filter"))) 425 }