container.go 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477
  1. package docker
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "github.com/dotcloud/docker/archive"
  7. "github.com/dotcloud/docker/execdriver"
  8. "github.com/dotcloud/docker/graphdriver"
  9. "github.com/dotcloud/docker/pkg/mount"
  10. "github.com/dotcloud/docker/pkg/term"
  11. "github.com/dotcloud/docker/utils"
  12. "github.com/kr/pty"
  13. "io"
  14. "io/ioutil"
  15. "log"
  16. "net"
  17. "os"
  18. "path"
  19. "strings"
  20. "sync"
  21. "syscall"
  22. "time"
  23. )
  24. var (
  25. ErrNotATTY = errors.New("The PTY is not a file")
  26. ErrNoTTY = errors.New("No PTY found")
  27. )
  28. type Container struct {
  29. sync.Mutex
  30. root string // Path to the "home" of the container, including metadata.
  31. rootfs string // Path to the root filesystem of the container.
  32. ID string
  33. Created time.Time
  34. Path string
  35. Args []string
  36. Config *Config
  37. State State
  38. Image string
  39. network *NetworkInterface
  40. NetworkSettings *NetworkSettings
  41. ResolvConfPath string
  42. HostnamePath string
  43. HostsPath string
  44. Name string
  45. Driver string
  46. process *execdriver.Process
  47. stdout *utils.WriteBroadcaster
  48. stderr *utils.WriteBroadcaster
  49. stdin io.ReadCloser
  50. stdinPipe io.WriteCloser
  51. ptyMaster io.Closer
  52. runtime *Runtime
  53. waitLock chan struct{}
  54. Volumes map[string]string
  55. // Store rw/ro in a separate structure to preserve reverse-compatibility on-disk.
  56. // Easier than migrating older container configs :)
  57. VolumesRW map[string]bool
  58. hostConfig *HostConfig
  59. activeLinks map[string]*Link
  60. }
  61. // Note: the Config structure should hold only portable information about the container.
  62. // Here, "portable" means "independent from the host we are running on".
  63. // Non-portable information *should* appear in HostConfig.
  64. type Config struct {
  65. Hostname string
  66. Domainname string
  67. User string
  68. Memory int64 // Memory limit (in bytes)
  69. MemorySwap int64 // Total memory usage (memory + swap); set `-1' to disable swap
  70. CpuShares int64 // CPU shares (relative weight vs. other containers)
  71. AttachStdin bool
  72. AttachStdout bool
  73. AttachStderr bool
  74. PortSpecs []string // Deprecated - Can be in the format of 8080/tcp
  75. ExposedPorts map[Port]struct{}
  76. Tty bool // Attach standard streams to a tty, including stdin if it is not closed.
  77. OpenStdin bool // Open stdin
  78. StdinOnce bool // If true, close stdin after the 1 attached client disconnects.
  79. Env []string
  80. Cmd []string
  81. Dns []string
  82. Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
  83. Volumes map[string]struct{}
  84. VolumesFrom string
  85. WorkingDir string
  86. Entrypoint []string
  87. NetworkDisabled bool
  88. }
  89. type HostConfig struct {
  90. Binds []string
  91. ContainerIDFile string
  92. LxcConf []KeyValuePair
  93. Privileged bool
  94. PortBindings map[Port][]PortBinding
  95. Links []string
  96. PublishAllPorts bool
  97. }
  98. type BindMap struct {
  99. SrcPath string
  100. DstPath string
  101. Mode string
  102. }
  103. var (
  104. ErrContainerStart = errors.New("The container failed to start. Unknown error")
  105. ErrContainerStartTimeout = errors.New("The container failed to start due to timed out.")
  106. ErrInvalidWorikingDirectory = errors.New("The working directory is invalid. It needs to be an absolute path.")
  107. ErrConflictAttachDetach = errors.New("Conflicting options: -a and -d")
  108. ErrConflictDetachAutoRemove = errors.New("Conflicting options: -rm and -d")
  109. )
  110. type KeyValuePair struct {
  111. Key string
  112. Value string
  113. }
  114. type PortBinding struct {
  115. HostIp string
  116. HostPort string
  117. }
  118. // 80/tcp
  119. type Port string
  120. func (p Port) Proto() string {
  121. parts := strings.Split(string(p), "/")
  122. if len(parts) == 1 {
  123. return "tcp"
  124. }
  125. return parts[1]
  126. }
  127. func (p Port) Port() string {
  128. return strings.Split(string(p), "/")[0]
  129. }
  130. func (p Port) Int() int {
  131. i, err := parsePort(p.Port())
  132. if err != nil {
  133. panic(err)
  134. }
  135. return i
  136. }
  137. func NewPort(proto, port string) Port {
  138. return Port(fmt.Sprintf("%s/%s", port, proto))
  139. }
  140. type PortMapping map[string]string // Deprecated
  141. type NetworkSettings struct {
  142. IPAddress string
  143. IPPrefixLen int
  144. Gateway string
  145. Bridge string
  146. PortMapping map[string]PortMapping // Deprecated
  147. Ports map[Port][]PortBinding
  148. }
  149. func (settings *NetworkSettings) PortMappingAPI() []APIPort {
  150. var mapping []APIPort
  151. for port, bindings := range settings.Ports {
  152. p, _ := parsePort(port.Port())
  153. if len(bindings) == 0 {
  154. mapping = append(mapping, APIPort{
  155. PublicPort: int64(p),
  156. Type: port.Proto(),
  157. })
  158. continue
  159. }
  160. for _, binding := range bindings {
  161. p, _ := parsePort(port.Port())
  162. h, _ := parsePort(binding.HostPort)
  163. mapping = append(mapping, APIPort{
  164. PrivatePort: int64(p),
  165. PublicPort: int64(h),
  166. Type: port.Proto(),
  167. IP: binding.HostIp,
  168. })
  169. }
  170. }
  171. return mapping
  172. }
  173. // Inject the io.Reader at the given path. Note: do not close the reader
  174. func (container *Container) Inject(file io.Reader, pth string) error {
  175. if err := container.EnsureMounted(); err != nil {
  176. return fmt.Errorf("inject: error mounting container %s: %s", container.ID, err)
  177. }
  178. // Return error if path exists
  179. destPath := path.Join(container.RootfsPath(), pth)
  180. if _, err := os.Stat(destPath); err == nil {
  181. // Since err is nil, the path could be stat'd and it exists
  182. return fmt.Errorf("%s exists", pth)
  183. } else if !os.IsNotExist(err) {
  184. // Expect err might be that the file doesn't exist, so
  185. // if it's some other error, return that.
  186. return err
  187. }
  188. // Make sure the directory exists
  189. if err := os.MkdirAll(path.Join(container.RootfsPath(), path.Dir(pth)), 0755); err != nil {
  190. return err
  191. }
  192. dest, err := os.Create(destPath)
  193. if err != nil {
  194. return err
  195. }
  196. defer dest.Close()
  197. if _, err := io.Copy(dest, file); err != nil {
  198. return err
  199. }
  200. return nil
  201. }
  202. func (container *Container) When() time.Time {
  203. return container.Created
  204. }
  205. func (container *Container) FromDisk() error {
  206. data, err := ioutil.ReadFile(container.jsonPath())
  207. if err != nil {
  208. return err
  209. }
  210. // Load container settings
  211. // udp broke compat of docker.PortMapping, but it's not used when loading a container, we can skip it
  212. if err := json.Unmarshal(data, container); err != nil && !strings.Contains(err.Error(), "docker.PortMapping") {
  213. return err
  214. }
  215. return container.readHostConfig()
  216. }
  217. func (container *Container) ToDisk() (err error) {
  218. data, err := json.Marshal(container)
  219. if err != nil {
  220. return
  221. }
  222. err = ioutil.WriteFile(container.jsonPath(), data, 0666)
  223. if err != nil {
  224. return
  225. }
  226. return container.writeHostConfig()
  227. }
  228. func (container *Container) readHostConfig() error {
  229. container.hostConfig = &HostConfig{}
  230. // If the hostconfig file does not exist, do not read it.
  231. // (We still have to initialize container.hostConfig,
  232. // but that's OK, since we just did that above.)
  233. _, err := os.Stat(container.hostConfigPath())
  234. if os.IsNotExist(err) {
  235. return nil
  236. }
  237. data, err := ioutil.ReadFile(container.hostConfigPath())
  238. if err != nil {
  239. return err
  240. }
  241. return json.Unmarshal(data, container.hostConfig)
  242. }
  243. func (container *Container) writeHostConfig() (err error) {
  244. data, err := json.Marshal(container.hostConfig)
  245. if err != nil {
  246. return
  247. }
  248. return ioutil.WriteFile(container.hostConfigPath(), data, 0666)
  249. }
  250. func (container *Container) generateEnvConfig(env []string) error {
  251. data, err := json.Marshal(env)
  252. if err != nil {
  253. return err
  254. }
  255. p, err := container.EnvConfigPath()
  256. if err != nil {
  257. return err
  258. }
  259. ioutil.WriteFile(p, data, 0600)
  260. return nil
  261. }
  262. func (container *Container) setupPty() error {
  263. ptyMaster, ptySlave, err := pty.Open()
  264. if err != nil {
  265. return err
  266. }
  267. container.ptyMaster = ptyMaster
  268. container.process.Stdout = ptySlave
  269. container.process.Stderr = ptySlave
  270. // Copy the PTYs to our broadcasters
  271. go func() {
  272. defer container.stdout.CloseWriters()
  273. utils.Debugf("startPty: begin of stdout pipe")
  274. io.Copy(container.stdout, ptyMaster)
  275. utils.Debugf("startPty: end of stdout pipe")
  276. }()
  277. // stdin
  278. if container.Config.OpenStdin {
  279. container.process.Stdin = ptySlave
  280. container.process.SysProcAttr.Setctty = true
  281. go func() {
  282. defer container.stdin.Close()
  283. utils.Debugf("startPty: begin of stdin pipe")
  284. io.Copy(ptyMaster, container.stdin)
  285. utils.Debugf("startPty: end of stdin pipe")
  286. }()
  287. }
  288. return nil
  289. }
  290. func (container *Container) setupStd() error {
  291. container.process.Stdout = container.stdout
  292. container.process.Stderr = container.stderr
  293. if container.Config.OpenStdin {
  294. stdin, err := container.process.StdinPipe()
  295. if err != nil {
  296. return err
  297. }
  298. go func() {
  299. defer stdin.Close()
  300. utils.Debugf("start: begin of stdin pipe")
  301. io.Copy(stdin, container.stdin)
  302. utils.Debugf("start: end of stdin pipe")
  303. }()
  304. }
  305. return nil
  306. }
  307. func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, stdout io.Writer, stderr io.Writer) chan error {
  308. var cStdout, cStderr io.ReadCloser
  309. var nJobs int
  310. errors := make(chan error, 3)
  311. if stdin != nil && container.Config.OpenStdin {
  312. nJobs += 1
  313. if cStdin, err := container.StdinPipe(); err != nil {
  314. errors <- err
  315. } else {
  316. go func() {
  317. utils.Debugf("attach: stdin: begin")
  318. defer utils.Debugf("attach: stdin: end")
  319. // No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr
  320. if container.Config.StdinOnce && !container.Config.Tty {
  321. defer cStdin.Close()
  322. } else {
  323. defer func() {
  324. if cStdout != nil {
  325. cStdout.Close()
  326. }
  327. if cStderr != nil {
  328. cStderr.Close()
  329. }
  330. }()
  331. }
  332. if container.Config.Tty {
  333. _, err = utils.CopyEscapable(cStdin, stdin)
  334. } else {
  335. _, err = io.Copy(cStdin, stdin)
  336. }
  337. if err == io.ErrClosedPipe {
  338. err = nil
  339. }
  340. if err != nil {
  341. utils.Errorf("attach: stdin: %s", err)
  342. }
  343. errors <- err
  344. }()
  345. }
  346. }
  347. if stdout != nil {
  348. nJobs += 1
  349. if p, err := container.StdoutPipe(); err != nil {
  350. errors <- err
  351. } else {
  352. cStdout = p
  353. go func() {
  354. utils.Debugf("attach: stdout: begin")
  355. defer utils.Debugf("attach: stdout: end")
  356. // If we are in StdinOnce mode, then close stdin
  357. if container.Config.StdinOnce && stdin != nil {
  358. defer stdin.Close()
  359. }
  360. if stdinCloser != nil {
  361. defer stdinCloser.Close()
  362. }
  363. _, err := io.Copy(stdout, cStdout)
  364. if err == io.ErrClosedPipe {
  365. err = nil
  366. }
  367. if err != nil {
  368. utils.Errorf("attach: stdout: %s", err)
  369. }
  370. errors <- err
  371. }()
  372. }
  373. } else {
  374. go func() {
  375. if stdinCloser != nil {
  376. defer stdinCloser.Close()
  377. }
  378. if cStdout, err := container.StdoutPipe(); err != nil {
  379. utils.Errorf("attach: stdout pipe: %s", err)
  380. } else {
  381. io.Copy(&utils.NopWriter{}, cStdout)
  382. }
  383. }()
  384. }
  385. if stderr != nil {
  386. nJobs += 1
  387. if p, err := container.StderrPipe(); err != nil {
  388. errors <- err
  389. } else {
  390. cStderr = p
  391. go func() {
  392. utils.Debugf("attach: stderr: begin")
  393. defer utils.Debugf("attach: stderr: end")
  394. // If we are in StdinOnce mode, then close stdin
  395. if container.Config.StdinOnce && stdin != nil {
  396. defer stdin.Close()
  397. }
  398. if stdinCloser != nil {
  399. defer stdinCloser.Close()
  400. }
  401. _, err := io.Copy(stderr, cStderr)
  402. if err == io.ErrClosedPipe {
  403. err = nil
  404. }
  405. if err != nil {
  406. utils.Errorf("attach: stderr: %s", err)
  407. }
  408. errors <- err
  409. }()
  410. }
  411. } else {
  412. go func() {
  413. if stdinCloser != nil {
  414. defer stdinCloser.Close()
  415. }
  416. if cStderr, err := container.StderrPipe(); err != nil {
  417. utils.Errorf("attach: stdout pipe: %s", err)
  418. } else {
  419. io.Copy(&utils.NopWriter{}, cStderr)
  420. }
  421. }()
  422. }
  423. return utils.Go(func() error {
  424. defer func() {
  425. if cStdout != nil {
  426. cStdout.Close()
  427. }
  428. if cStderr != nil {
  429. cStderr.Close()
  430. }
  431. }()
  432. // FIXME: how to clean up the stdin goroutine without the unwanted side effect
  433. // of closing the passed stdin? Add an intermediary io.Pipe?
  434. for i := 0; i < nJobs; i += 1 {
  435. utils.Debugf("attach: waiting for job %d/%d", i+1, nJobs)
  436. if err := <-errors; err != nil {
  437. utils.Errorf("attach: job %d returned error %s, aborting all jobs", i+1, err)
  438. return err
  439. }
  440. utils.Debugf("attach: job %d completed successfully", i+1)
  441. }
  442. utils.Debugf("attach: all jobs completed successfully")
  443. return nil
  444. })
  445. }
  446. func (container *Container) Start() (err error) {
  447. container.Lock()
  448. defer container.Unlock()
  449. if container.State.IsRunning() {
  450. return fmt.Errorf("The container %s is already running.", container.ID)
  451. }
  452. defer func() {
  453. if err != nil {
  454. container.cleanup()
  455. }
  456. }()
  457. if err := container.EnsureMounted(); err != nil {
  458. return err
  459. }
  460. if container.runtime.networkManager.disabled {
  461. container.Config.NetworkDisabled = true
  462. container.buildHostnameAndHostsFiles("127.0.1.1")
  463. } else {
  464. if err := container.allocateNetwork(); err != nil {
  465. return err
  466. }
  467. container.buildHostnameAndHostsFiles(container.NetworkSettings.IPAddress)
  468. }
  469. // Make sure the config is compatible with the current kernel
  470. if container.Config.Memory > 0 && !container.runtime.sysInfo.MemoryLimit {
  471. log.Printf("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n")
  472. container.Config.Memory = 0
  473. }
  474. if container.Config.Memory > 0 && !container.runtime.sysInfo.SwapLimit {
  475. log.Printf("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n")
  476. container.Config.MemorySwap = -1
  477. }
  478. if container.runtime.sysInfo.IPv4ForwardingDisabled {
  479. log.Printf("WARNING: IPv4 forwarding is disabled. Networking will not work")
  480. }
  481. if container.Volumes == nil || len(container.Volumes) == 0 {
  482. container.Volumes = make(map[string]string)
  483. container.VolumesRW = make(map[string]bool)
  484. }
  485. // Apply volumes from another container if requested
  486. if err := container.applyExternalVolumes(); err != nil {
  487. return err
  488. }
  489. if err := container.createVolumes(); err != nil {
  490. return err
  491. }
  492. // Setup environment
  493. env := []string{
  494. "HOME=/",
  495. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  496. "HOSTNAME=" + container.Config.Hostname,
  497. }
  498. if container.Config.Tty {
  499. env = append(env, "TERM=xterm")
  500. }
  501. // Init any links between the parent and children
  502. runtime := container.runtime
  503. children, err := runtime.Children(container.Name)
  504. if err != nil {
  505. return err
  506. }
  507. if len(children) > 0 {
  508. container.activeLinks = make(map[string]*Link, len(children))
  509. // If we encounter an error make sure that we rollback any network
  510. // config and ip table changes
  511. rollback := func() {
  512. for _, link := range container.activeLinks {
  513. link.Disable()
  514. }
  515. container.activeLinks = nil
  516. }
  517. for p, child := range children {
  518. link, err := NewLink(container, child, p, runtime.networkManager.bridgeIface)
  519. if err != nil {
  520. rollback()
  521. return err
  522. }
  523. container.activeLinks[link.Alias()] = link
  524. if err := link.Enable(); err != nil {
  525. rollback()
  526. return err
  527. }
  528. for _, envVar := range link.ToEnv() {
  529. env = append(env, envVar)
  530. }
  531. }
  532. }
  533. for _, elem := range container.Config.Env {
  534. env = append(env, elem)
  535. }
  536. if err := container.generateEnvConfig(env); err != nil {
  537. return err
  538. }
  539. var workingDir string
  540. if container.Config.WorkingDir != "" {
  541. workingDir = path.Clean(container.Config.WorkingDir)
  542. if err := os.MkdirAll(path.Join(container.RootfsPath(), workingDir), 0755); err != nil {
  543. return nil
  544. }
  545. }
  546. root := container.RootfsPath()
  547. envPath, err := container.EnvConfigPath()
  548. if err != nil {
  549. return err
  550. }
  551. // Mount docker specific files into the containers root fs
  552. if err := mount.Mount(runtime.sysInitPath, path.Join(root, "/.dockerinit"), "none", "bind,ro"); err != nil {
  553. return err
  554. }
  555. if err := mount.Mount(envPath, path.Join(root, "/.dockerenv"), "none", "bind,ro"); err != nil {
  556. return err
  557. }
  558. if err := mount.Mount(container.ResolvConfPath, path.Join(root, "/etc/resolv.conf"), "none", "bind,ro"); err != nil {
  559. return err
  560. }
  561. if container.HostnamePath != "" && container.HostsPath != "" {
  562. if err := mount.Mount(container.HostnamePath, path.Join(root, "/etc/hostname"), "none", "bind,ro"); err != nil {
  563. return err
  564. }
  565. if err := mount.Mount(container.HostsPath, path.Join(root, "/etc/hosts"), "none", "bind,ro"); err != nil {
  566. return err
  567. }
  568. }
  569. // Mount user specified volumes
  570. for r, v := range container.Volumes {
  571. mountAs := "ro"
  572. if container.VolumesRW[r] {
  573. mountAs = "rw"
  574. }
  575. if err := mount.Mount(v, path.Join(root, r), "none", fmt.Sprintf("bind,%s", mountAs)); err != nil {
  576. return err
  577. }
  578. }
  579. var (
  580. en *execdriver.Network
  581. driverConfig []string
  582. )
  583. if !container.Config.NetworkDisabled {
  584. network := container.NetworkSettings
  585. en = &execdriver.Network{
  586. Gateway: network.Gateway,
  587. Bridge: network.Bridge,
  588. IPAddress: network.IPAddress,
  589. IPPrefixLen: network.IPPrefixLen,
  590. Mtu: container.runtime.config.Mtu,
  591. }
  592. }
  593. if lxcConf := container.hostConfig.LxcConf; lxcConf != nil {
  594. for _, pair := range lxcConf {
  595. driverConfig = append(driverConfig, fmt.Sprintf("%s = %s", pair.Key, pair.Value))
  596. }
  597. }
  598. resources := &execdriver.Resources{
  599. Memory: container.Config.Memory,
  600. MemorySwap: container.Config.MemorySwap,
  601. CpuShares: container.Config.CpuShares,
  602. }
  603. container.process = &execdriver.Process{
  604. ID: container.ID,
  605. Privileged: container.hostConfig.Privileged,
  606. Rootfs: root,
  607. InitPath: "/.dockerinit",
  608. Entrypoint: container.Path,
  609. Arguments: container.Args,
  610. WorkingDir: workingDir,
  611. Network: en,
  612. Tty: container.Config.Tty,
  613. User: container.Config.User,
  614. Config: driverConfig,
  615. Resources: resources,
  616. }
  617. container.process.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
  618. // Setup logging of stdout and stderr to disk
  619. if err := container.runtime.LogToDisk(container.stdout, container.logPath("json"), "stdout"); err != nil {
  620. return err
  621. }
  622. if err := container.runtime.LogToDisk(container.stderr, container.logPath("json"), "stderr"); err != nil {
  623. return err
  624. }
  625. container.waitLock = make(chan struct{})
  626. // Setuping pipes and/or Pty
  627. var setup func() error
  628. if container.Config.Tty {
  629. setup = container.setupPty
  630. } else {
  631. setup = container.setupStd
  632. }
  633. if err := setup(); err != nil {
  634. return err
  635. }
  636. callbackLock := make(chan struct{})
  637. callback := func(process *execdriver.Process) {
  638. container.State.SetRunning(process.Pid())
  639. if process.Tty {
  640. // The callback is called after the process Start()
  641. // so we are in the parent process. In TTY mode, stdin/out/err is the PtySlace
  642. // which we close here.
  643. if c, ok := process.Stdout.(io.Closer); ok {
  644. c.Close()
  645. }
  646. }
  647. if err := container.ToDisk(); err != nil {
  648. utils.Debugf("%s", err)
  649. }
  650. close(callbackLock)
  651. }
  652. // We use a callback here instead of a goroutine and an chan for
  653. // syncronization purposes
  654. cErr := utils.Go(func() error { return container.monitor(callback) })
  655. // Start should not return until the process is actually running
  656. select {
  657. case <-callbackLock:
  658. case err := <-cErr:
  659. return err
  660. }
  661. return nil
  662. }
  663. func (container *Container) getBindMap() (map[string]BindMap, error) {
  664. // Create the requested bind mounts
  665. binds := make(map[string]BindMap)
  666. // Define illegal container destinations
  667. illegalDsts := []string{"/", "."}
  668. for _, bind := range container.hostConfig.Binds {
  669. // FIXME: factorize bind parsing in parseBind
  670. var src, dst, mode string
  671. arr := strings.Split(bind, ":")
  672. if len(arr) == 2 {
  673. src = arr[0]
  674. dst = arr[1]
  675. mode = "rw"
  676. } else if len(arr) == 3 {
  677. src = arr[0]
  678. dst = arr[1]
  679. mode = arr[2]
  680. } else {
  681. return nil, fmt.Errorf("Invalid bind specification: %s", bind)
  682. }
  683. // Bail if trying to mount to an illegal destination
  684. for _, illegal := range illegalDsts {
  685. if dst == illegal {
  686. return nil, fmt.Errorf("Illegal bind destination: %s", dst)
  687. }
  688. }
  689. bindMap := BindMap{
  690. SrcPath: src,
  691. DstPath: dst,
  692. Mode: mode,
  693. }
  694. binds[path.Clean(dst)] = bindMap
  695. }
  696. return binds, nil
  697. }
  698. func (container *Container) createVolumes() error {
  699. binds, err := container.getBindMap()
  700. if err != nil {
  701. return err
  702. }
  703. volumesDriver := container.runtime.volumes.driver
  704. // Create the requested volumes if they don't exist
  705. for volPath := range container.Config.Volumes {
  706. volPath = path.Clean(volPath)
  707. volIsDir := true
  708. // Skip existing volumes
  709. if _, exists := container.Volumes[volPath]; exists {
  710. continue
  711. }
  712. var srcPath string
  713. var isBindMount bool
  714. srcRW := false
  715. // If an external bind is defined for this volume, use that as a source
  716. if bindMap, exists := binds[volPath]; exists {
  717. isBindMount = true
  718. srcPath = bindMap.SrcPath
  719. if strings.ToLower(bindMap.Mode) == "rw" {
  720. srcRW = true
  721. }
  722. if stat, err := os.Lstat(bindMap.SrcPath); err != nil {
  723. return err
  724. } else {
  725. volIsDir = stat.IsDir()
  726. }
  727. // Otherwise create an directory in $ROOT/volumes/ and use that
  728. } else {
  729. // Do not pass a container as the parameter for the volume creation.
  730. // The graph driver using the container's information ( Image ) to
  731. // create the parent.
  732. c, err := container.runtime.volumes.Create(nil, nil, "", "", nil)
  733. if err != nil {
  734. return err
  735. }
  736. srcPath, err = volumesDriver.Get(c.ID)
  737. if err != nil {
  738. return fmt.Errorf("Driver %s failed to get volume rootfs %s: %s", volumesDriver, c.ID, err)
  739. }
  740. srcRW = true // RW by default
  741. }
  742. container.Volumes[volPath] = srcPath
  743. container.VolumesRW[volPath] = srcRW
  744. // Create the mountpoint
  745. volPath = path.Join(container.RootfsPath(), volPath)
  746. rootVolPath, err := utils.FollowSymlinkInScope(volPath, container.RootfsPath())
  747. if err != nil {
  748. return err
  749. }
  750. if _, err := os.Stat(rootVolPath); err != nil {
  751. if os.IsNotExist(err) {
  752. if volIsDir {
  753. if err := os.MkdirAll(rootVolPath, 0755); err != nil {
  754. return err
  755. }
  756. } else {
  757. if err := os.MkdirAll(path.Dir(rootVolPath), 0755); err != nil {
  758. return err
  759. }
  760. if f, err := os.OpenFile(rootVolPath, os.O_CREATE, 0755); err != nil {
  761. return err
  762. } else {
  763. f.Close()
  764. }
  765. }
  766. }
  767. }
  768. // Do not copy or change permissions if we are mounting from the host
  769. if srcRW && !isBindMount {
  770. volList, err := ioutil.ReadDir(rootVolPath)
  771. if err != nil {
  772. return err
  773. }
  774. if len(volList) > 0 {
  775. srcList, err := ioutil.ReadDir(srcPath)
  776. if err != nil {
  777. return err
  778. }
  779. if len(srcList) == 0 {
  780. // If the source volume is empty copy files from the root into the volume
  781. if err := archive.CopyWithTar(rootVolPath, srcPath); err != nil {
  782. return err
  783. }
  784. var stat syscall.Stat_t
  785. if err := syscall.Stat(rootVolPath, &stat); err != nil {
  786. return err
  787. }
  788. var srcStat syscall.Stat_t
  789. if err := syscall.Stat(srcPath, &srcStat); err != nil {
  790. return err
  791. }
  792. // Change the source volume's ownership if it differs from the root
  793. // files that where just copied
  794. if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid {
  795. if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil {
  796. return err
  797. }
  798. }
  799. }
  800. }
  801. }
  802. }
  803. return nil
  804. }
  805. func (container *Container) applyExternalVolumes() error {
  806. if container.Config.VolumesFrom != "" {
  807. containerSpecs := strings.Split(container.Config.VolumesFrom, ",")
  808. for _, containerSpec := range containerSpecs {
  809. mountRW := true
  810. specParts := strings.SplitN(containerSpec, ":", 2)
  811. switch len(specParts) {
  812. case 0:
  813. return fmt.Errorf("Malformed volumes-from specification: %s", container.Config.VolumesFrom)
  814. case 2:
  815. switch specParts[1] {
  816. case "ro":
  817. mountRW = false
  818. case "rw": // mountRW is already true
  819. default:
  820. return fmt.Errorf("Malformed volumes-from speficication: %s", containerSpec)
  821. }
  822. }
  823. c := container.runtime.Get(specParts[0])
  824. if c == nil {
  825. return fmt.Errorf("Container %s not found. Impossible to mount its volumes", container.ID)
  826. }
  827. for volPath, id := range c.Volumes {
  828. if _, exists := container.Volumes[volPath]; exists {
  829. continue
  830. }
  831. if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
  832. return err
  833. }
  834. container.Volumes[volPath] = id
  835. if isRW, exists := c.VolumesRW[volPath]; exists {
  836. container.VolumesRW[volPath] = isRW && mountRW
  837. }
  838. }
  839. }
  840. }
  841. return nil
  842. }
  843. func (container *Container) Run() error {
  844. if err := container.Start(); err != nil {
  845. return err
  846. }
  847. container.Wait()
  848. return nil
  849. }
  850. func (container *Container) Output() (output []byte, err error) {
  851. pipe, err := container.StdoutPipe()
  852. if err != nil {
  853. return nil, err
  854. }
  855. defer pipe.Close()
  856. if err := container.Start(); err != nil {
  857. return nil, err
  858. }
  859. output, err = ioutil.ReadAll(pipe)
  860. container.Wait()
  861. return output, err
  862. }
  863. // Container.StdinPipe returns a WriteCloser which can be used to feed data
  864. // to the standard input of the container's active process.
  865. // Container.StdoutPipe and Container.StderrPipe each return a ReadCloser
  866. // which can be used to retrieve the standard output (and error) generated
  867. // by the container's active process. The output (and error) are actually
  868. // copied and delivered to all StdoutPipe and StderrPipe consumers, using
  869. // a kind of "broadcaster".
  870. func (container *Container) StdinPipe() (io.WriteCloser, error) {
  871. return container.stdinPipe, nil
  872. }
  873. func (container *Container) StdoutPipe() (io.ReadCloser, error) {
  874. reader, writer := io.Pipe()
  875. container.stdout.AddWriter(writer, "")
  876. return utils.NewBufReader(reader), nil
  877. }
  878. func (container *Container) StderrPipe() (io.ReadCloser, error) {
  879. reader, writer := io.Pipe()
  880. container.stderr.AddWriter(writer, "")
  881. return utils.NewBufReader(reader), nil
  882. }
  883. func (container *Container) buildHostnameAndHostsFiles(IP string) {
  884. container.HostnamePath = path.Join(container.root, "hostname")
  885. ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644)
  886. hostsContent := []byte(`
  887. 127.0.0.1 localhost
  888. ::1 localhost ip6-localhost ip6-loopback
  889. fe00::0 ip6-localnet
  890. ff00::0 ip6-mcastprefix
  891. ff02::1 ip6-allnodes
  892. ff02::2 ip6-allrouters
  893. `)
  894. container.HostsPath = path.Join(container.root, "hosts")
  895. if container.Config.Domainname != "" {
  896. hostsContent = append([]byte(fmt.Sprintf("%s\t%s.%s %s\n", IP, container.Config.Hostname, container.Config.Domainname, container.Config.Hostname)), hostsContent...)
  897. } else if !container.Config.NetworkDisabled {
  898. hostsContent = append([]byte(fmt.Sprintf("%s\t%s\n", IP, container.Config.Hostname)), hostsContent...)
  899. }
  900. ioutil.WriteFile(container.HostsPath, hostsContent, 0644)
  901. }
  902. func (container *Container) allocateNetwork() error {
  903. if container.Config.NetworkDisabled {
  904. return nil
  905. }
  906. var (
  907. iface *NetworkInterface
  908. err error
  909. )
  910. if container.State.IsGhost() {
  911. if manager := container.runtime.networkManager; manager.disabled {
  912. iface = &NetworkInterface{disabled: true}
  913. } else {
  914. iface = &NetworkInterface{
  915. IPNet: net.IPNet{IP: net.ParseIP(container.NetworkSettings.IPAddress), Mask: manager.bridgeNetwork.Mask},
  916. Gateway: manager.bridgeNetwork.IP,
  917. manager: manager,
  918. }
  919. if iface != nil && iface.IPNet.IP != nil {
  920. ipNum := ipToInt(iface.IPNet.IP)
  921. manager.ipAllocator.inUse[ipNum] = struct{}{}
  922. } else {
  923. iface, err = container.runtime.networkManager.Allocate()
  924. if err != nil {
  925. return err
  926. }
  927. }
  928. }
  929. } else {
  930. iface, err = container.runtime.networkManager.Allocate()
  931. if err != nil {
  932. return err
  933. }
  934. }
  935. if container.Config.PortSpecs != nil {
  936. utils.Debugf("Migrating port mappings for container: %s", strings.Join(container.Config.PortSpecs, ", "))
  937. if err := migratePortMappings(container.Config, container.hostConfig); err != nil {
  938. return err
  939. }
  940. container.Config.PortSpecs = nil
  941. if err := container.writeHostConfig(); err != nil {
  942. return err
  943. }
  944. }
  945. var (
  946. portSpecs = make(map[Port]struct{})
  947. bindings = make(map[Port][]PortBinding)
  948. )
  949. if !container.State.IsGhost() {
  950. if container.Config.ExposedPorts != nil {
  951. portSpecs = container.Config.ExposedPorts
  952. }
  953. if container.hostConfig.PortBindings != nil {
  954. bindings = container.hostConfig.PortBindings
  955. }
  956. } else {
  957. if container.NetworkSettings.Ports != nil {
  958. for port, binding := range container.NetworkSettings.Ports {
  959. portSpecs[port] = struct{}{}
  960. bindings[port] = binding
  961. }
  962. }
  963. }
  964. container.NetworkSettings.PortMapping = nil
  965. for port := range portSpecs {
  966. binding := bindings[port]
  967. if container.hostConfig.PublishAllPorts && len(binding) == 0 {
  968. binding = append(binding, PortBinding{})
  969. }
  970. for i := 0; i < len(binding); i++ {
  971. b := binding[i]
  972. nat, err := iface.AllocatePort(port, b)
  973. if err != nil {
  974. iface.Release()
  975. return err
  976. }
  977. utils.Debugf("Allocate port: %s:%s->%s", nat.Binding.HostIp, port, nat.Binding.HostPort)
  978. binding[i] = nat.Binding
  979. }
  980. bindings[port] = binding
  981. }
  982. container.writeHostConfig()
  983. container.NetworkSettings.Ports = bindings
  984. container.network = iface
  985. container.NetworkSettings.Bridge = container.runtime.networkManager.bridgeIface
  986. container.NetworkSettings.IPAddress = iface.IPNet.IP.String()
  987. container.NetworkSettings.IPPrefixLen, _ = iface.IPNet.Mask.Size()
  988. container.NetworkSettings.Gateway = iface.Gateway.String()
  989. return nil
  990. }
  991. func (container *Container) releaseNetwork() {
  992. if container.Config.NetworkDisabled || container.network == nil {
  993. return
  994. }
  995. container.network.Release()
  996. container.network = nil
  997. container.NetworkSettings = &NetworkSettings{}
  998. }
  999. func (container *Container) monitor(callback execdriver.StartCallback) error {
  1000. var (
  1001. err error
  1002. exitCode int
  1003. )
  1004. if container.process == nil {
  1005. // This happends when you have a GHOST container with lxc
  1006. err = container.runtime.WaitGhost(container)
  1007. } else {
  1008. exitCode, err = container.runtime.Run(container, callback)
  1009. }
  1010. if err != nil {
  1011. if container.runtime != nil && container.runtime.srv != nil {
  1012. container.runtime.srv.LogEvent("die", container.ID, container.runtime.repositories.ImageName(container.Image))
  1013. }
  1014. }
  1015. // Cleanup
  1016. container.cleanup()
  1017. // Re-create a brand new stdin pipe once the container exited
  1018. if container.Config.OpenStdin {
  1019. container.stdin, container.stdinPipe = io.Pipe()
  1020. }
  1021. container.State.SetStopped(exitCode)
  1022. close(container.waitLock)
  1023. // FIXME: there is a race condition here which causes this to fail during the unit tests.
  1024. // If another goroutine was waiting for Wait() to return before removing the container's root
  1025. // from the filesystem... At this point it may already have done so.
  1026. // This is because State.setStopped() has already been called, and has caused Wait()
  1027. // to return.
  1028. // FIXME: why are we serializing running state to disk in the first place?
  1029. //log.Printf("%s: Failed to dump configuration to the disk: %s", container.ID, err)
  1030. container.ToDisk()
  1031. return err
  1032. }
  1033. func (container *Container) cleanup() {
  1034. container.releaseNetwork()
  1035. // Disable all active links
  1036. if container.activeLinks != nil {
  1037. for _, link := range container.activeLinks {
  1038. link.Disable()
  1039. }
  1040. }
  1041. if container.Config.OpenStdin {
  1042. if err := container.stdin.Close(); err != nil {
  1043. utils.Errorf("%s: Error close stdin: %s", container.ID, err)
  1044. }
  1045. }
  1046. if err := container.stdout.CloseWriters(); err != nil {
  1047. utils.Errorf("%s: Error close stdout: %s", container.ID, err)
  1048. }
  1049. if err := container.stderr.CloseWriters(); err != nil {
  1050. utils.Errorf("%s: Error close stderr: %s", container.ID, err)
  1051. }
  1052. if container.ptyMaster != nil {
  1053. if err := container.ptyMaster.Close(); err != nil {
  1054. utils.Errorf("%s: Error closing Pty master: %s", container.ID, err)
  1055. }
  1056. }
  1057. if err := container.Unmount(); err != nil {
  1058. log.Printf("%v: Failed to umount filesystem: %v", container.ID, err)
  1059. }
  1060. }
  1061. func (container *Container) kill(sig int) error {
  1062. container.Lock()
  1063. defer container.Unlock()
  1064. if !container.State.IsRunning() {
  1065. return nil
  1066. }
  1067. return container.runtime.Kill(container, sig)
  1068. }
  1069. func (container *Container) Kill() error {
  1070. if !container.State.IsRunning() {
  1071. return nil
  1072. }
  1073. // 1. Send SIGKILL
  1074. if err := container.kill(9); err != nil {
  1075. return err
  1076. }
  1077. // 2. Wait for the process to die, in last resort, try to kill the process directly
  1078. if err := container.WaitTimeout(10 * time.Second); err != nil {
  1079. if container.process == nil {
  1080. return fmt.Errorf("lxc-kill failed, impossible to kill the container %s", utils.TruncateID(container.ID))
  1081. }
  1082. log.Printf("Container %s failed to exit within 10 seconds of lxc-kill %s - trying direct SIGKILL", "SIGKILL", utils.TruncateID(container.ID))
  1083. if err := container.runtime.Kill(container, 9); err != nil {
  1084. return err
  1085. }
  1086. }
  1087. container.Wait()
  1088. return nil
  1089. }
  1090. func (container *Container) Stop(seconds int) error {
  1091. if !container.State.IsRunning() {
  1092. return nil
  1093. }
  1094. // 1. Send a SIGTERM
  1095. if err := container.kill(15); err != nil {
  1096. utils.Debugf("Error sending kill SIGTERM: %s", err)
  1097. log.Print("Failed to send SIGTERM to the process, force killing")
  1098. if err := container.kill(9); err != nil {
  1099. return err
  1100. }
  1101. }
  1102. // 2. Wait for the process to exit on its own
  1103. if err := container.WaitTimeout(time.Duration(seconds) * time.Second); err != nil {
  1104. log.Printf("Container %v failed to exit within %d seconds of SIGTERM - using the force", container.ID, seconds)
  1105. // 3. If it doesn't, then send SIGKILL
  1106. if err := container.Kill(); err != nil {
  1107. return err
  1108. }
  1109. }
  1110. return nil
  1111. }
  1112. func (container *Container) Restart(seconds int) error {
  1113. if err := container.Stop(seconds); err != nil {
  1114. return err
  1115. }
  1116. return container.Start()
  1117. }
  1118. // Wait blocks until the container stops running, then returns its exit code.
  1119. func (container *Container) Wait() int {
  1120. <-container.waitLock
  1121. return container.State.GetExitCode()
  1122. }
  1123. func (container *Container) Resize(h, w int) error {
  1124. pty, ok := container.ptyMaster.(*os.File)
  1125. if !ok {
  1126. return fmt.Errorf("ptyMaster does not have Fd() method")
  1127. }
  1128. return term.SetWinsize(pty.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)})
  1129. }
  1130. func (container *Container) ExportRw() (archive.Archive, error) {
  1131. if err := container.EnsureMounted(); err != nil {
  1132. return nil, err
  1133. }
  1134. if container.runtime == nil {
  1135. return nil, fmt.Errorf("Can't load storage driver for unregistered container %s", container.ID)
  1136. }
  1137. return container.runtime.Diff(container)
  1138. }
  1139. func (container *Container) Export() (archive.Archive, error) {
  1140. if err := container.EnsureMounted(); err != nil {
  1141. return nil, err
  1142. }
  1143. return archive.Tar(container.RootfsPath(), archive.Uncompressed)
  1144. }
  1145. func (container *Container) WaitTimeout(timeout time.Duration) error {
  1146. done := make(chan bool)
  1147. go func() {
  1148. container.Wait()
  1149. done <- true
  1150. }()
  1151. select {
  1152. case <-time.After(timeout):
  1153. return fmt.Errorf("Timed Out")
  1154. case <-done:
  1155. return nil
  1156. }
  1157. }
  1158. func (container *Container) EnsureMounted() error {
  1159. // FIXME: EnsureMounted is deprecated because drivers are now responsible
  1160. // for re-entrant mounting in their Get() method.
  1161. return container.Mount()
  1162. }
  1163. func (container *Container) Mount() error {
  1164. return container.runtime.Mount(container)
  1165. }
  1166. func (container *Container) Changes() ([]archive.Change, error) {
  1167. return container.runtime.Changes(container)
  1168. }
  1169. func (container *Container) GetImage() (*Image, error) {
  1170. if container.runtime == nil {
  1171. return nil, fmt.Errorf("Can't get image of unregistered container")
  1172. }
  1173. return container.runtime.graph.Get(container.Image)
  1174. }
  1175. func (container *Container) Unmount() error {
  1176. var (
  1177. err error
  1178. root = container.RootfsPath()
  1179. mounts = []string{
  1180. path.Join(root, "/.dockerinit"),
  1181. path.Join(root, "/.dockerenv"),
  1182. path.Join(root, "/etc/resolv.conf"),
  1183. }
  1184. )
  1185. if container.HostnamePath != "" && container.HostsPath != "" {
  1186. mounts = append(mounts, path.Join(root, "/etc/hostname"), path.Join(root, "/etc/hosts"))
  1187. }
  1188. for r := range container.Volumes {
  1189. mounts = append(mounts, path.Join(root, r))
  1190. }
  1191. for _, m := range mounts {
  1192. if lastError := mount.Unmount(m); lastError != nil {
  1193. err = lastError
  1194. }
  1195. }
  1196. if err != nil {
  1197. return err
  1198. }
  1199. return container.runtime.Unmount(container)
  1200. }
  1201. func (container *Container) logPath(name string) string {
  1202. return path.Join(container.root, fmt.Sprintf("%s-%s.log", container.ID, name))
  1203. }
  1204. func (container *Container) ReadLog(name string) (io.Reader, error) {
  1205. return os.Open(container.logPath(name))
  1206. }
  1207. func (container *Container) hostConfigPath() string {
  1208. return path.Join(container.root, "hostconfig.json")
  1209. }
  1210. func (container *Container) jsonPath() string {
  1211. return path.Join(container.root, "config.json")
  1212. }
  1213. func (container *Container) EnvConfigPath() (string, error) {
  1214. p := path.Join(container.root, "config.env")
  1215. if _, err := os.Stat(p); err != nil {
  1216. if os.IsNotExist(err) {
  1217. f, err := os.Create(p)
  1218. if err != nil {
  1219. return "", err
  1220. }
  1221. f.Close()
  1222. } else {
  1223. return "", err
  1224. }
  1225. }
  1226. return p, nil
  1227. }
  1228. // This method must be exported to be used from the lxc template
  1229. func (container *Container) RootfsPath() string {
  1230. return container.rootfs
  1231. }
  1232. func validateID(id string) error {
  1233. if id == "" {
  1234. return fmt.Errorf("Invalid empty id")
  1235. }
  1236. return nil
  1237. }
  1238. // GetSize, return real size, virtual size
  1239. func (container *Container) GetSize() (int64, int64) {
  1240. var (
  1241. sizeRw, sizeRootfs int64
  1242. err error
  1243. driver = container.runtime.driver
  1244. )
  1245. if err := container.EnsureMounted(); err != nil {
  1246. utils.Errorf("Warning: failed to compute size of container rootfs %s: %s", container.ID, err)
  1247. return sizeRw, sizeRootfs
  1248. }
  1249. if differ, ok := container.runtime.driver.(graphdriver.Differ); ok {
  1250. sizeRw, err = differ.DiffSize(container.ID)
  1251. if err != nil {
  1252. utils.Errorf("Warning: driver %s couldn't return diff size of container %s: %s", driver, container.ID, err)
  1253. // FIXME: GetSize should return an error. Not changing it now in case
  1254. // there is a side-effect.
  1255. sizeRw = -1
  1256. }
  1257. } else {
  1258. changes, _ := container.Changes()
  1259. if changes != nil {
  1260. sizeRw = archive.ChangesSize(container.RootfsPath(), changes)
  1261. } else {
  1262. sizeRw = -1
  1263. }
  1264. }
  1265. if _, err = os.Stat(container.RootfsPath()); err != nil {
  1266. if sizeRootfs, err = utils.TreeSize(container.RootfsPath()); err != nil {
  1267. sizeRootfs = -1
  1268. }
  1269. }
  1270. return sizeRw, sizeRootfs
  1271. }
  1272. func (container *Container) Copy(resource string) (archive.Archive, error) {
  1273. if err := container.EnsureMounted(); err != nil {
  1274. return nil, err
  1275. }
  1276. var filter []string
  1277. basePath := path.Join(container.RootfsPath(), resource)
  1278. stat, err := os.Stat(basePath)
  1279. if err != nil {
  1280. return nil, err
  1281. }
  1282. if !stat.IsDir() {
  1283. d, f := path.Split(basePath)
  1284. basePath = d
  1285. filter = []string{f}
  1286. } else {
  1287. filter = []string{path.Base(basePath)}
  1288. basePath = path.Dir(basePath)
  1289. }
  1290. return archive.TarFilter(basePath, &archive.TarOptions{
  1291. Compression: archive.Uncompressed,
  1292. Includes: filter,
  1293. Recursive: true,
  1294. })
  1295. }
  1296. // Returns true if the container exposes a certain port
  1297. func (container *Container) Exposes(p Port) bool {
  1298. _, exists := container.Config.ExposedPorts[p]
  1299. return exists
  1300. }
  1301. func (container *Container) GetPtyMaster() (*os.File, error) {
  1302. if container.ptyMaster == nil {
  1303. return nil, ErrNoTTY
  1304. }
  1305. if pty, ok := container.ptyMaster.(*os.File); ok {
  1306. return pty, nil
  1307. }
  1308. return nil, ErrNotATTY
  1309. }