server.go 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164
  1. package docker
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "github.com/dotcloud/docker/archive"
  7. "github.com/dotcloud/docker/auth"
  8. "github.com/dotcloud/docker/cgroups"
  9. "github.com/dotcloud/docker/engine"
  10. "github.com/dotcloud/docker/pkg/graphdb"
  11. "github.com/dotcloud/docker/registry"
  12. "github.com/dotcloud/docker/utils"
  13. "io"
  14. "io/ioutil"
  15. "log"
  16. "net/http"
  17. "net/url"
  18. "os"
  19. "os/exec"
  20. "os/signal"
  21. "path"
  22. "path/filepath"
  23. "runtime"
  24. "strconv"
  25. "strings"
  26. "sync"
  27. "syscall"
  28. "time"
  29. )
  30. func (srv *Server) Close() error {
  31. return srv.runtime.Close()
  32. }
  33. func init() {
  34. engine.Register("initapi", jobInitApi)
  35. }
  36. // jobInitApi runs the remote api server `srv` as a daemon,
  37. // Only one api server can run at the same time - this is enforced by a pidfile.
  38. // The signals SIGINT, SIGQUIT and SIGTERM are intercepted for cleanup.
  39. func jobInitApi(job *engine.Job) engine.Status {
  40. job.Logf("Creating server")
  41. // FIXME: ImportEnv deprecates ConfigFromJob
  42. srv, err := NewServer(job.Eng, ConfigFromJob(job))
  43. if err != nil {
  44. job.Error(err)
  45. return engine.StatusErr
  46. }
  47. if srv.runtime.config.Pidfile != "" {
  48. job.Logf("Creating pidfile")
  49. if err := utils.CreatePidFile(srv.runtime.config.Pidfile); err != nil {
  50. // FIXME: do we need fatal here instead of returning a job error?
  51. log.Fatal(err)
  52. }
  53. }
  54. job.Logf("Setting up signal traps")
  55. c := make(chan os.Signal, 1)
  56. signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
  57. go func() {
  58. sig := <-c
  59. log.Printf("Received signal '%v', exiting\n", sig)
  60. utils.RemovePidFile(srv.runtime.config.Pidfile)
  61. srv.Close()
  62. os.Exit(0)
  63. }()
  64. job.Eng.Hack_SetGlobalVar("httpapi.server", srv)
  65. job.Eng.Hack_SetGlobalVar("httpapi.runtime", srv.runtime)
  66. // https://github.com/dotcloud/docker/issues/2768
  67. if srv.runtime.networkManager.bridgeNetwork != nil {
  68. job.Eng.Hack_SetGlobalVar("httpapi.bridgeIP", srv.runtime.networkManager.bridgeNetwork.IP)
  69. }
  70. if err := job.Eng.Register("export", srv.ContainerExport); err != nil {
  71. job.Error(err)
  72. return engine.StatusErr
  73. }
  74. if err := job.Eng.Register("create", srv.ContainerCreate); err != nil {
  75. job.Error(err)
  76. return engine.StatusErr
  77. }
  78. if err := job.Eng.Register("stop", srv.ContainerStop); err != nil {
  79. job.Error(err)
  80. return engine.StatusErr
  81. }
  82. if err := job.Eng.Register("restart", srv.ContainerRestart); err != nil {
  83. job.Error(err)
  84. return engine.StatusErr
  85. }
  86. if err := job.Eng.Register("start", srv.ContainerStart); err != nil {
  87. job.Error(err)
  88. return engine.StatusErr
  89. }
  90. if err := job.Eng.Register("kill", srv.ContainerKill); err != nil {
  91. job.Error(err)
  92. return engine.StatusErr
  93. }
  94. if err := job.Eng.Register("serveapi", srv.ListenAndServe); err != nil {
  95. job.Error(err)
  96. return engine.StatusErr
  97. }
  98. if err := job.Eng.Register("wait", srv.ContainerWait); err != nil {
  99. job.Error(err)
  100. return engine.StatusErr
  101. }
  102. if err := job.Eng.Register("tag", srv.ImageTag); err != nil {
  103. job.Error(err)
  104. return engine.StatusErr
  105. }
  106. if err := job.Eng.Register("resize", srv.ContainerResize); err != nil {
  107. job.Error(err)
  108. return engine.StatusErr
  109. }
  110. if err := job.Eng.Register("commit", srv.ContainerCommit); err != nil {
  111. job.Error(err)
  112. return engine.StatusErr
  113. }
  114. if err := job.Eng.Register("info", srv.DockerInfo); err != nil {
  115. job.Error(err)
  116. return engine.StatusErr
  117. }
  118. if err := job.Eng.Register("container_delete", srv.ContainerDestroy); err != nil {
  119. job.Error(err)
  120. return engine.StatusErr
  121. }
  122. if err := job.Eng.Register("image_export", srv.ImageExport); err != nil {
  123. job.Error(err)
  124. return engine.StatusErr
  125. }
  126. if err := job.Eng.Register("images", srv.Images); err != nil {
  127. job.Error(err)
  128. return engine.StatusErr
  129. }
  130. if err := job.Eng.Register("history", srv.ImageHistory); err != nil {
  131. job.Error(err)
  132. return engine.StatusErr
  133. }
  134. if err := job.Eng.Register("viz", srv.ImagesViz); err != nil {
  135. job.Error(err)
  136. return engine.StatusErr
  137. }
  138. if err := job.Eng.Register("container_copy", srv.ContainerCopy); err != nil {
  139. job.Error(err)
  140. return engine.StatusErr
  141. }
  142. return engine.StatusOK
  143. }
  144. func (srv *Server) ListenAndServe(job *engine.Job) engine.Status {
  145. protoAddrs := job.Args
  146. chErrors := make(chan error, len(protoAddrs))
  147. for _, protoAddr := range protoAddrs {
  148. protoAddrParts := strings.SplitN(protoAddr, "://", 2)
  149. switch protoAddrParts[0] {
  150. case "unix":
  151. if err := syscall.Unlink(protoAddrParts[1]); err != nil && !os.IsNotExist(err) {
  152. log.Fatal(err)
  153. }
  154. case "tcp":
  155. if !strings.HasPrefix(protoAddrParts[1], "127.0.0.1") {
  156. log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
  157. }
  158. default:
  159. job.Errorf("Invalid protocol format.")
  160. return engine.StatusErr
  161. }
  162. go func() {
  163. // FIXME: merge Server.ListenAndServe with ListenAndServe
  164. chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], srv, job.GetenvBool("Logging"))
  165. }()
  166. }
  167. for i := 0; i < len(protoAddrs); i += 1 {
  168. err := <-chErrors
  169. if err != nil {
  170. job.Error(err)
  171. return engine.StatusErr
  172. }
  173. }
  174. return engine.StatusOK
  175. }
  176. // simpleVersionInfo is a simple implementation of
  177. // the interface VersionInfo, which is used
  178. // to provide version information for some product,
  179. // component, etc. It stores the product name and the version
  180. // in string and returns them on calls to Name() and Version().
  181. type simpleVersionInfo struct {
  182. name string
  183. version string
  184. }
  185. func (v *simpleVersionInfo) Name() string {
  186. return v.name
  187. }
  188. func (v *simpleVersionInfo) Version() string {
  189. return v.version
  190. }
  191. // ContainerKill send signal to the container
  192. // If no signal is given (sig 0), then Kill with SIGKILL and wait
  193. // for the container to exit.
  194. // If a signal is given, then just send it to the container and return.
  195. func (srv *Server) ContainerKill(job *engine.Job) engine.Status {
  196. if n := len(job.Args); n < 1 || n > 2 {
  197. job.Errorf("Usage: %s CONTAINER [SIGNAL]", job.Name)
  198. return engine.StatusErr
  199. }
  200. name := job.Args[0]
  201. var sig uint64
  202. if len(job.Args) == 2 && job.Args[1] != "" {
  203. var err error
  204. // The largest legal signal is 31, so let's parse on 5 bits
  205. sig, err = strconv.ParseUint(job.Args[1], 10, 5)
  206. if err != nil {
  207. job.Errorf("Invalid signal: %s", job.Args[1])
  208. return engine.StatusErr
  209. }
  210. }
  211. if container := srv.runtime.Get(name); container != nil {
  212. // If no signal is passed, perform regular Kill (SIGKILL + wait())
  213. if sig == 0 {
  214. if err := container.Kill(); err != nil {
  215. job.Errorf("Cannot kill container %s: %s", name, err)
  216. return engine.StatusErr
  217. }
  218. srv.LogEvent("kill", container.ID, srv.runtime.repositories.ImageName(container.Image))
  219. } else {
  220. // Otherwise, just send the requested signal
  221. if err := container.kill(int(sig)); err != nil {
  222. job.Errorf("Cannot kill container %s: %s", name, err)
  223. return engine.StatusErr
  224. }
  225. // FIXME: Add event for signals
  226. }
  227. } else {
  228. job.Errorf("No such container: %s", name)
  229. return engine.StatusErr
  230. }
  231. return engine.StatusOK
  232. }
  233. func (srv *Server) ContainerExport(job *engine.Job) engine.Status {
  234. if len(job.Args) != 1 {
  235. job.Errorf("Usage: %s container_id", job.Name)
  236. return engine.StatusErr
  237. }
  238. name := job.Args[0]
  239. if container := srv.runtime.Get(name); container != nil {
  240. data, err := container.Export()
  241. if err != nil {
  242. job.Errorf("%s: %s", name, err)
  243. return engine.StatusErr
  244. }
  245. // Stream the entire contents of the container (basically a volatile snapshot)
  246. if _, err := io.Copy(job.Stdout, data); err != nil {
  247. job.Errorf("%s: %s", name, err)
  248. return engine.StatusErr
  249. }
  250. // FIXME: factor job-specific LogEvent to engine.Job.Run()
  251. srv.LogEvent("export", container.ID, srv.runtime.repositories.ImageName(container.Image))
  252. return engine.StatusOK
  253. }
  254. job.Errorf("No such container: %s", name)
  255. return engine.StatusErr
  256. }
  257. // ImageExport exports all images with the given tag. All versions
  258. // containing the same tag are exported. The resulting output is an
  259. // uncompressed tar ball.
  260. // name is the set of tags to export.
  261. // out is the writer where the images are written to.
  262. func (srv *Server) ImageExport(job *engine.Job) engine.Status {
  263. if len(job.Args) != 1 {
  264. job.Errorf("Usage: %s CONTAINER\n", job.Name)
  265. return engine.StatusErr
  266. }
  267. name := job.Args[0]
  268. // get image json
  269. tempdir, err := ioutil.TempDir("", "docker-export-")
  270. if err != nil {
  271. job.Error(err)
  272. return engine.StatusErr
  273. }
  274. defer os.RemoveAll(tempdir)
  275. utils.Debugf("Serializing %s", name)
  276. rootRepo, err := srv.runtime.repositories.Get(name)
  277. if err != nil {
  278. job.Error(err)
  279. return engine.StatusErr
  280. }
  281. if rootRepo != nil {
  282. for _, id := range rootRepo {
  283. image, err := srv.ImageInspect(id)
  284. if err != nil {
  285. job.Error(err)
  286. return engine.StatusErr
  287. }
  288. if err := srv.exportImage(image, tempdir); err != nil {
  289. job.Error(err)
  290. return engine.StatusErr
  291. }
  292. }
  293. // write repositories
  294. rootRepoMap := map[string]Repository{}
  295. rootRepoMap[name] = rootRepo
  296. rootRepoJson, _ := json.Marshal(rootRepoMap)
  297. if err := ioutil.WriteFile(path.Join(tempdir, "repositories"), rootRepoJson, os.ModeAppend); err != nil {
  298. job.Error(err)
  299. return engine.StatusErr
  300. }
  301. } else {
  302. image, err := srv.ImageInspect(name)
  303. if err != nil {
  304. job.Error(err)
  305. return engine.StatusErr
  306. }
  307. if err := srv.exportImage(image, tempdir); err != nil {
  308. job.Error(err)
  309. return engine.StatusErr
  310. }
  311. }
  312. fs, err := archive.Tar(tempdir, archive.Uncompressed)
  313. if err != nil {
  314. job.Error(err)
  315. return engine.StatusErr
  316. }
  317. if _, err := io.Copy(job.Stdout, fs); err != nil {
  318. job.Error(err)
  319. return engine.StatusErr
  320. }
  321. return engine.StatusOK
  322. }
  323. func (srv *Server) exportImage(image *Image, tempdir string) error {
  324. for i := image; i != nil; {
  325. // temporary directory
  326. tmpImageDir := path.Join(tempdir, i.ID)
  327. if err := os.Mkdir(tmpImageDir, os.ModeDir); err != nil {
  328. if os.IsExist(err) {
  329. return nil
  330. }
  331. return err
  332. }
  333. var version = "1.0"
  334. var versionBuf = []byte(version)
  335. if err := ioutil.WriteFile(path.Join(tmpImageDir, "VERSION"), versionBuf, os.ModeAppend); err != nil {
  336. return err
  337. }
  338. // serialize json
  339. b, err := json.Marshal(i)
  340. if err != nil {
  341. return err
  342. }
  343. if err := ioutil.WriteFile(path.Join(tmpImageDir, "json"), b, os.ModeAppend); err != nil {
  344. return err
  345. }
  346. // serialize filesystem
  347. fs, err := i.TarLayer()
  348. if err != nil {
  349. return err
  350. }
  351. fsTar, err := os.Create(path.Join(tmpImageDir, "layer.tar"))
  352. if err != nil {
  353. return err
  354. }
  355. if _, err = io.Copy(fsTar, fs); err != nil {
  356. return err
  357. }
  358. fsTar.Close()
  359. // find parent
  360. if i.Parent != "" {
  361. i, err = srv.ImageInspect(i.Parent)
  362. if err != nil {
  363. return err
  364. }
  365. } else {
  366. i = nil
  367. }
  368. }
  369. return nil
  370. }
  371. // Loads a set of images into the repository. This is the complementary of ImageExport.
  372. // The input stream is an uncompressed tar ball containing images and metadata.
  373. func (srv *Server) ImageLoad(in io.Reader) error {
  374. tmpImageDir, err := ioutil.TempDir("", "docker-import-")
  375. if err != nil {
  376. return err
  377. }
  378. defer os.RemoveAll(tmpImageDir)
  379. var (
  380. repoTarFile = path.Join(tmpImageDir, "repo.tar")
  381. repoDir = path.Join(tmpImageDir, "repo")
  382. )
  383. tarFile, err := os.Create(repoTarFile)
  384. if err != nil {
  385. return err
  386. }
  387. if _, err := io.Copy(tarFile, in); err != nil {
  388. return err
  389. }
  390. tarFile.Close()
  391. repoFile, err := os.Open(repoTarFile)
  392. if err != nil {
  393. return err
  394. }
  395. if err := os.Mkdir(repoDir, os.ModeDir); err != nil {
  396. return err
  397. }
  398. if err := archive.Untar(repoFile, repoDir, nil); err != nil {
  399. return err
  400. }
  401. dirs, err := ioutil.ReadDir(repoDir)
  402. if err != nil {
  403. return err
  404. }
  405. for _, d := range dirs {
  406. if d.IsDir() {
  407. if err := srv.recursiveLoad(d.Name(), tmpImageDir); err != nil {
  408. return err
  409. }
  410. }
  411. }
  412. repositoriesJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", "repositories"))
  413. if err == nil {
  414. repositories := map[string]Repository{}
  415. if err := json.Unmarshal(repositoriesJson, &repositories); err != nil {
  416. return err
  417. }
  418. for imageName, tagMap := range repositories {
  419. for tag, address := range tagMap {
  420. if err := srv.runtime.repositories.Set(imageName, tag, address, true); err != nil {
  421. return err
  422. }
  423. }
  424. }
  425. } else if !os.IsNotExist(err) {
  426. return err
  427. }
  428. return nil
  429. }
  430. func (srv *Server) recursiveLoad(address, tmpImageDir string) error {
  431. if _, err := srv.ImageInspect(address); err != nil {
  432. utils.Debugf("Loading %s", address)
  433. imageJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", address, "json"))
  434. if err != nil {
  435. utils.Debugf("Error reading json", err)
  436. return err
  437. }
  438. layer, err := os.Open(path.Join(tmpImageDir, "repo", address, "layer.tar"))
  439. if err != nil {
  440. utils.Debugf("Error reading embedded tar", err)
  441. return err
  442. }
  443. img, err := NewImgJSON(imageJson)
  444. if err != nil {
  445. utils.Debugf("Error unmarshalling json", err)
  446. return err
  447. }
  448. if img.Parent != "" {
  449. if !srv.runtime.graph.Exists(img.Parent) {
  450. if err := srv.recursiveLoad(img.Parent, tmpImageDir); err != nil {
  451. return err
  452. }
  453. }
  454. }
  455. if err := srv.runtime.graph.Register(imageJson, layer, img); err != nil {
  456. return err
  457. }
  458. }
  459. utils.Debugf("Completed processing %s", address)
  460. return nil
  461. }
  462. func (srv *Server) ImagesSearch(term string) ([]registry.SearchResult, error) {
  463. r, err := registry.NewRegistry(nil, srv.HTTPRequestFactory(nil), auth.IndexServerAddress())
  464. if err != nil {
  465. return nil, err
  466. }
  467. results, err := r.SearchRepositories(term)
  468. if err != nil {
  469. return nil, err
  470. }
  471. return results.Results, nil
  472. }
  473. func (srv *Server) ImageInsert(name, url, path string, out io.Writer, sf *utils.StreamFormatter) error {
  474. out = utils.NewWriteFlusher(out)
  475. img, err := srv.runtime.repositories.LookupImage(name)
  476. if err != nil {
  477. return err
  478. }
  479. file, err := utils.Download(url)
  480. if err != nil {
  481. return err
  482. }
  483. defer file.Body.Close()
  484. config, _, _, err := ParseRun([]string{img.ID, "echo", "insert", url, path}, srv.runtime.capabilities)
  485. if err != nil {
  486. return err
  487. }
  488. c, _, err := srv.runtime.Create(config, "")
  489. if err != nil {
  490. return err
  491. }
  492. if err := c.Inject(utils.ProgressReader(file.Body, int(file.ContentLength), out, sf, false, "", "Downloading"), path); err != nil {
  493. return err
  494. }
  495. // FIXME: Handle custom repo, tag comment, author
  496. img, err = srv.runtime.Commit(c, "", "", img.Comment, img.Author, nil)
  497. if err != nil {
  498. return err
  499. }
  500. out.Write(sf.FormatStatus(img.ID, ""))
  501. return nil
  502. }
  503. func (srv *Server) ImagesViz(job *engine.Job) engine.Status {
  504. images, _ := srv.runtime.graph.Map()
  505. if images == nil {
  506. return engine.StatusOK
  507. }
  508. job.Stdout.Write([]byte("digraph docker {\n"))
  509. var (
  510. parentImage *Image
  511. err error
  512. )
  513. for _, image := range images {
  514. parentImage, err = image.GetParent()
  515. if err != nil {
  516. job.Errorf("Error while getting parent image: %v", err)
  517. return engine.StatusErr
  518. }
  519. if parentImage != nil {
  520. job.Stdout.Write([]byte(" \"" + parentImage.ID + "\" -> \"" + image.ID + "\"\n"))
  521. } else {
  522. job.Stdout.Write([]byte(" base -> \"" + image.ID + "\" [style=invis]\n"))
  523. }
  524. }
  525. reporefs := make(map[string][]string)
  526. for name, repository := range srv.runtime.repositories.Repositories {
  527. for tag, id := range repository {
  528. reporefs[utils.TruncateID(id)] = append(reporefs[utils.TruncateID(id)], fmt.Sprintf("%s:%s", name, tag))
  529. }
  530. }
  531. for id, repos := range reporefs {
  532. job.Stdout.Write([]byte(" \"" + id + "\" [label=\"" + id + "\\n" + strings.Join(repos, "\\n") + "\",shape=box,fillcolor=\"paleturquoise\",style=\"filled,rounded\"];\n"))
  533. }
  534. job.Stdout.Write([]byte(" base [style=invisible]\n}\n"))
  535. return engine.StatusOK
  536. }
  537. func (srv *Server) Images(job *engine.Job) engine.Status {
  538. var (
  539. allImages map[string]*Image
  540. err error
  541. )
  542. if job.GetenvBool("all") {
  543. allImages, err = srv.runtime.graph.Map()
  544. } else {
  545. allImages, err = srv.runtime.graph.Heads()
  546. }
  547. if err != nil {
  548. job.Error(err)
  549. return engine.StatusErr
  550. }
  551. lookup := make(map[string]*engine.Env)
  552. for name, repository := range srv.runtime.repositories.Repositories {
  553. if job.Getenv("filter") != "" {
  554. if match, _ := path.Match(job.Getenv("filter"), name); !match {
  555. continue
  556. }
  557. }
  558. for tag, id := range repository {
  559. image, err := srv.runtime.graph.Get(id)
  560. if err != nil {
  561. log.Printf("Warning: couldn't load %s from %s/%s: %s", id, name, tag, err)
  562. continue
  563. }
  564. if out, exists := lookup[id]; exists {
  565. out.SetList("RepoTags", append(out.GetList("RepoTags"), fmt.Sprintf("%s:%s", name, tag)))
  566. } else {
  567. out := &engine.Env{}
  568. delete(allImages, id)
  569. out.Set("ParentId", image.Parent)
  570. out.SetList("RepoTags", []string{fmt.Sprintf("%s:%s", name, tag)})
  571. out.Set("ID", image.ID)
  572. out.SetInt64("Created", image.Created.Unix())
  573. out.SetInt64("Size", image.Size)
  574. out.SetInt64("VirtualSize", image.getParentsSize(0)+image.Size)
  575. lookup[id] = out
  576. }
  577. }
  578. }
  579. outs := engine.NewTable("Created", len(lookup))
  580. for _, value := range lookup {
  581. outs.Add(value)
  582. }
  583. // Display images which aren't part of a repository/tag
  584. if job.Getenv("filter") == "" {
  585. for _, image := range allImages {
  586. out := &engine.Env{}
  587. out.Set("ParentId", image.Parent)
  588. out.SetList("RepoTags", []string{"<none>:<none>"})
  589. out.Set("ID", image.ID)
  590. out.SetInt64("Created", image.Created.Unix())
  591. out.SetInt64("Size", image.Size)
  592. out.SetInt64("VirtualSize", image.getParentsSize(0)+image.Size)
  593. outs.Add(out)
  594. }
  595. }
  596. outs.ReverseSort()
  597. if _, err := outs.WriteTo(job.Stdout); err != nil {
  598. job.Error(err)
  599. return engine.StatusErr
  600. }
  601. return engine.StatusOK
  602. }
  603. func (srv *Server) DockerInfo(job *engine.Job) engine.Status {
  604. images, _ := srv.runtime.graph.Map()
  605. var imgcount int
  606. if images == nil {
  607. imgcount = 0
  608. } else {
  609. imgcount = len(images)
  610. }
  611. lxcVersion := ""
  612. if output, err := exec.Command("lxc-version").CombinedOutput(); err == nil {
  613. outputStr := string(output)
  614. if len(strings.SplitN(outputStr, ":", 2)) == 2 {
  615. lxcVersion = strings.TrimSpace(strings.SplitN(string(output), ":", 2)[1])
  616. }
  617. }
  618. kernelVersion := "<unknown>"
  619. if kv, err := utils.GetKernelVersion(); err == nil {
  620. kernelVersion = kv.String()
  621. }
  622. // if we still have the original dockerinit binary from before we copied it locally, let's return the path to that, since that's more intuitive (the copied path is trivial to derive by hand given VERSION)
  623. initPath := utils.DockerInitPath("")
  624. if initPath == "" {
  625. // if that fails, we'll just return the path from the runtime
  626. initPath = srv.runtime.sysInitPath
  627. }
  628. v := &engine.Env{}
  629. v.SetInt("Containers", len(srv.runtime.List()))
  630. v.SetInt("Images", imgcount)
  631. v.Set("Driver", srv.runtime.driver.String())
  632. v.SetJson("DriverStatus", srv.runtime.driver.Status())
  633. v.SetBool("MemoryLimit", srv.runtime.capabilities.MemoryLimit)
  634. v.SetBool("SwapLimit", srv.runtime.capabilities.SwapLimit)
  635. v.SetBool("IPv4Forwarding", !srv.runtime.capabilities.IPv4ForwardingDisabled)
  636. v.SetBool("Debug", os.Getenv("DEBUG") != "")
  637. v.SetInt("NFd", utils.GetTotalUsedFds())
  638. v.SetInt("NGoroutines", runtime.NumGoroutine())
  639. v.Set("LXCVersion", lxcVersion)
  640. v.SetInt("NEventsListener", len(srv.events))
  641. v.Set("KernelVersion", kernelVersion)
  642. v.Set("IndexServerAddress", auth.IndexServerAddress())
  643. v.Set("InitSha1", utils.INITSHA1)
  644. v.Set("InitPath", initPath)
  645. if _, err := v.WriteTo(job.Stdout); err != nil {
  646. job.Error(err)
  647. return engine.StatusErr
  648. }
  649. return engine.StatusOK
  650. }
  651. func (srv *Server) ImageHistory(job *engine.Job) engine.Status {
  652. if n := len(job.Args); n != 1 {
  653. job.Errorf("Usage: %s IMAGE", job.Name)
  654. return engine.StatusErr
  655. }
  656. name := job.Args[0]
  657. image, err := srv.runtime.repositories.LookupImage(name)
  658. if err != nil {
  659. job.Error(err)
  660. return engine.StatusErr
  661. }
  662. lookupMap := make(map[string][]string)
  663. for name, repository := range srv.runtime.repositories.Repositories {
  664. for tag, id := range repository {
  665. // If the ID already has a reverse lookup, do not update it unless for "latest"
  666. if _, exists := lookupMap[id]; !exists {
  667. lookupMap[id] = []string{}
  668. }
  669. lookupMap[id] = append(lookupMap[id], name+":"+tag)
  670. }
  671. }
  672. outs := engine.NewTable("Created", 0)
  673. err = image.WalkHistory(func(img *Image) error {
  674. out := &engine.Env{}
  675. out.Set("ID", img.ID)
  676. out.SetInt64("Created", img.Created.Unix())
  677. out.Set("CreatedBy", strings.Join(img.ContainerConfig.Cmd, " "))
  678. out.SetList("Tags", lookupMap[img.ID])
  679. out.SetInt64("Size", img.Size)
  680. outs.Add(out)
  681. return nil
  682. })
  683. outs.ReverseSort()
  684. if _, err := outs.WriteTo(job.Stdout); err != nil {
  685. job.Error(err)
  686. return engine.StatusErr
  687. }
  688. return engine.StatusOK
  689. }
  690. func (srv *Server) ContainerTop(name, psArgs string) (*APITop, error) {
  691. if container := srv.runtime.Get(name); container != nil {
  692. if !container.State.IsRunning() {
  693. return nil, fmt.Errorf("Container %s is not running", name)
  694. }
  695. pids, err := cgroups.GetPidsForContainer(container.ID)
  696. if err != nil {
  697. return nil, err
  698. }
  699. if len(psArgs) == 0 {
  700. psArgs = "-ef"
  701. }
  702. output, err := exec.Command("ps", psArgs).Output()
  703. if err != nil {
  704. return nil, fmt.Errorf("Error running ps: %s", err)
  705. }
  706. lines := strings.Split(string(output), "\n")
  707. header := strings.Fields(lines[0])
  708. procs := APITop{
  709. Titles: header,
  710. }
  711. pidIndex := -1
  712. for i, name := range header {
  713. if name == "PID" {
  714. pidIndex = i
  715. }
  716. }
  717. if pidIndex == -1 {
  718. return nil, errors.New("Couldn't find PID field in ps output")
  719. }
  720. for _, line := range lines[1:] {
  721. if len(line) == 0 {
  722. continue
  723. }
  724. fields := strings.Fields(line)
  725. p, err := strconv.Atoi(fields[pidIndex])
  726. if err != nil {
  727. return nil, fmt.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err)
  728. }
  729. for _, pid := range pids {
  730. if pid == p {
  731. // Make sure number of fields equals number of header titles
  732. // merging "overhanging" fields
  733. processes := fields[:len(procs.Titles)-1]
  734. processes = append(processes, strings.Join(fields[len(procs.Titles)-1:], " "))
  735. procs.Processes = append(procs.Processes, processes)
  736. }
  737. }
  738. }
  739. return &procs, nil
  740. }
  741. return nil, fmt.Errorf("No such container: %s", name)
  742. }
  743. func (srv *Server) ContainerChanges(name string) ([]archive.Change, error) {
  744. if container := srv.runtime.Get(name); container != nil {
  745. return container.Changes()
  746. }
  747. return nil, fmt.Errorf("No such container: %s", name)
  748. }
  749. func (srv *Server) Containers(all, size bool, n int, since, before string) []APIContainers {
  750. var foundBefore bool
  751. var displayed int
  752. out := []APIContainers{}
  753. names := map[string][]string{}
  754. srv.runtime.containerGraph.Walk("/", func(p string, e *graphdb.Entity) error {
  755. names[e.ID()] = append(names[e.ID()], p)
  756. return nil
  757. }, -1)
  758. for _, container := range srv.runtime.List() {
  759. if !container.State.IsRunning() && !all && n == -1 && since == "" && before == "" {
  760. continue
  761. }
  762. if before != "" && !foundBefore {
  763. if container.ID == before || utils.TruncateID(container.ID) == before {
  764. foundBefore = true
  765. }
  766. continue
  767. }
  768. if displayed == n {
  769. break
  770. }
  771. if container.ID == since || utils.TruncateID(container.ID) == since {
  772. break
  773. }
  774. displayed++
  775. c := createAPIContainer(names[container.ID], container, size, srv.runtime)
  776. out = append(out, c)
  777. }
  778. return out
  779. }
  780. func createAPIContainer(names []string, container *Container, size bool, runtime *Runtime) APIContainers {
  781. c := APIContainers{
  782. ID: container.ID,
  783. }
  784. c.Names = names
  785. c.Image = runtime.repositories.ImageName(container.Image)
  786. c.Command = fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " "))
  787. c.Created = container.Created.Unix()
  788. c.Status = container.State.String()
  789. c.Ports = container.NetworkSettings.PortMappingAPI()
  790. if size {
  791. c.SizeRw, c.SizeRootFs = container.GetSize()
  792. }
  793. return c
  794. }
  795. func (srv *Server) ContainerCommit(job *engine.Job) engine.Status {
  796. if len(job.Args) != 1 {
  797. job.Errorf("Not enough arguments. Usage: %s CONTAINER\n", job.Name)
  798. return engine.StatusErr
  799. }
  800. name := job.Args[0]
  801. container := srv.runtime.Get(name)
  802. if container == nil {
  803. job.Errorf("No such container: %s", name)
  804. return engine.StatusErr
  805. }
  806. var config Config
  807. if err := job.GetenvJson("config", &config); err != nil {
  808. job.Error(err)
  809. return engine.StatusErr
  810. }
  811. img, err := srv.runtime.Commit(container, job.Getenv("repo"), job.Getenv("tag"), job.Getenv("comment"), job.Getenv("author"), &config)
  812. if err != nil {
  813. job.Error(err)
  814. return engine.StatusErr
  815. }
  816. job.Printf("%s\n", img.ID)
  817. return engine.StatusOK
  818. }
  819. func (srv *Server) ImageTag(job *engine.Job) engine.Status {
  820. if len(job.Args) != 2 && len(job.Args) != 3 {
  821. job.Errorf("Usage: %s IMAGE REPOSITORY [TAG]\n", job.Name)
  822. return engine.StatusErr
  823. }
  824. var tag string
  825. if len(job.Args) == 3 {
  826. tag = job.Args[2]
  827. }
  828. if err := srv.runtime.repositories.Set(job.Args[1], tag, job.Args[0], job.GetenvBool("force")); err != nil {
  829. job.Error(err)
  830. return engine.StatusErr
  831. }
  832. return engine.StatusOK
  833. }
  834. func (srv *Server) pullImage(r *registry.Registry, out io.Writer, imgID, endpoint string, token []string, sf *utils.StreamFormatter) error {
  835. history, err := r.GetRemoteHistory(imgID, endpoint, token)
  836. if err != nil {
  837. return err
  838. }
  839. out.Write(sf.FormatProgress(utils.TruncateID(imgID), "Pulling dependent layers", nil))
  840. // FIXME: Try to stream the images?
  841. // FIXME: Launch the getRemoteImage() in goroutines
  842. for i := len(history) - 1; i >= 0; i-- {
  843. id := history[i]
  844. // ensure no two downloads of the same layer happen at the same time
  845. if c, err := srv.poolAdd("pull", "layer:"+id); err != nil {
  846. utils.Errorf("Image (id: %s) pull is already running, skipping: %v", id, err)
  847. <-c
  848. }
  849. defer srv.poolRemove("pull", "layer:"+id)
  850. if !srv.runtime.graph.Exists(id) {
  851. out.Write(sf.FormatProgress(utils.TruncateID(id), "Pulling metadata", nil))
  852. imgJSON, imgSize, err := r.GetRemoteImageJSON(id, endpoint, token)
  853. if err != nil {
  854. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
  855. // FIXME: Keep going in case of error?
  856. return err
  857. }
  858. img, err := NewImgJSON(imgJSON)
  859. if err != nil {
  860. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
  861. return fmt.Errorf("Failed to parse json: %s", err)
  862. }
  863. // Get the layer
  864. out.Write(sf.FormatProgress(utils.TruncateID(id), "Pulling fs layer", nil))
  865. layer, err := r.GetRemoteImageLayer(img.ID, endpoint, token)
  866. if err != nil {
  867. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
  868. return err
  869. }
  870. defer layer.Close()
  871. if err := srv.runtime.graph.Register(imgJSON, utils.ProgressReader(layer, imgSize, out, sf, false, utils.TruncateID(id), "Downloading"), img); err != nil {
  872. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error downloading dependent layers", nil))
  873. return err
  874. }
  875. }
  876. out.Write(sf.FormatProgress(utils.TruncateID(id), "Download complete", nil))
  877. }
  878. return nil
  879. }
  880. func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, localName, remoteName, askedTag string, sf *utils.StreamFormatter, parallel bool) error {
  881. out.Write(sf.FormatStatus("", "Pulling repository %s", localName))
  882. repoData, err := r.GetRepositoryData(remoteName)
  883. if err != nil {
  884. return err
  885. }
  886. utils.Debugf("Retrieving the tag list")
  887. tagsList, err := r.GetRemoteTags(repoData.Endpoints, remoteName, repoData.Tokens)
  888. if err != nil {
  889. utils.Errorf("%v", err)
  890. return err
  891. }
  892. for tag, id := range tagsList {
  893. repoData.ImgList[id] = &registry.ImgData{
  894. ID: id,
  895. Tag: tag,
  896. Checksum: "",
  897. }
  898. }
  899. utils.Debugf("Registering tags")
  900. // If no tag has been specified, pull them all
  901. if askedTag == "" {
  902. for tag, id := range tagsList {
  903. repoData.ImgList[id].Tag = tag
  904. }
  905. } else {
  906. // Otherwise, check that the tag exists and use only that one
  907. id, exists := tagsList[askedTag]
  908. if !exists {
  909. return fmt.Errorf("Tag %s not found in repository %s", askedTag, localName)
  910. }
  911. repoData.ImgList[id].Tag = askedTag
  912. }
  913. errors := make(chan error)
  914. for _, image := range repoData.ImgList {
  915. downloadImage := func(img *registry.ImgData) {
  916. if askedTag != "" && img.Tag != askedTag {
  917. utils.Debugf("(%s) does not match %s (id: %s), skipping", img.Tag, askedTag, img.ID)
  918. if parallel {
  919. errors <- nil
  920. }
  921. return
  922. }
  923. if img.Tag == "" {
  924. utils.Debugf("Image (id: %s) present in this repository but untagged, skipping", img.ID)
  925. if parallel {
  926. errors <- nil
  927. }
  928. return
  929. }
  930. // ensure no two downloads of the same image happen at the same time
  931. if c, err := srv.poolAdd("pull", "img:"+img.ID); err != nil {
  932. if c != nil {
  933. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Layer already being pulled by another client. Waiting.", nil))
  934. <-c
  935. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Download complete", nil))
  936. } else {
  937. utils.Errorf("Image (id: %s) pull is already running, skipping: %v", img.ID, err)
  938. }
  939. if parallel {
  940. errors <- nil
  941. }
  942. return
  943. }
  944. defer srv.poolRemove("pull", "img:"+img.ID)
  945. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s", img.Tag, localName), nil))
  946. success := false
  947. var lastErr error
  948. for _, ep := range repoData.Endpoints {
  949. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s, endpoint: %s", img.Tag, localName, ep), nil))
  950. if err := srv.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
  951. // Its not ideal that only the last error is returned, it would be better to concatenate the errors.
  952. // As the error is also given to the output stream the user will see the error.
  953. lastErr = err
  954. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Error pulling image (%s) from %s, endpoint: %s, %s", img.Tag, localName, ep, err), nil))
  955. continue
  956. }
  957. success = true
  958. break
  959. }
  960. if !success {
  961. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Error pulling image (%s) from %s, %s", img.Tag, localName, lastErr), nil))
  962. if parallel {
  963. errors <- fmt.Errorf("Could not find repository on any of the indexed registries.")
  964. return
  965. }
  966. }
  967. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Download complete", nil))
  968. if parallel {
  969. errors <- nil
  970. }
  971. }
  972. if parallel {
  973. go downloadImage(image)
  974. } else {
  975. downloadImage(image)
  976. }
  977. }
  978. if parallel {
  979. var lastError error
  980. for i := 0; i < len(repoData.ImgList); i++ {
  981. if err := <-errors; err != nil {
  982. lastError = err
  983. }
  984. }
  985. if lastError != nil {
  986. return lastError
  987. }
  988. }
  989. for tag, id := range tagsList {
  990. if askedTag != "" && tag != askedTag {
  991. continue
  992. }
  993. if err := srv.runtime.repositories.Set(localName, tag, id, true); err != nil {
  994. return err
  995. }
  996. }
  997. if err := srv.runtime.repositories.Save(); err != nil {
  998. return err
  999. }
  1000. return nil
  1001. }
  1002. func (srv *Server) poolAdd(kind, key string) (chan struct{}, error) {
  1003. srv.Lock()
  1004. defer srv.Unlock()
  1005. if c, exists := srv.pullingPool[key]; exists {
  1006. return c, fmt.Errorf("pull %s is already in progress", key)
  1007. }
  1008. if c, exists := srv.pushingPool[key]; exists {
  1009. return c, fmt.Errorf("push %s is already in progress", key)
  1010. }
  1011. c := make(chan struct{})
  1012. switch kind {
  1013. case "pull":
  1014. srv.pullingPool[key] = c
  1015. case "push":
  1016. srv.pushingPool[key] = c
  1017. default:
  1018. return nil, fmt.Errorf("Unknown pool type")
  1019. }
  1020. return c, nil
  1021. }
  1022. func (srv *Server) poolRemove(kind, key string) error {
  1023. srv.Lock()
  1024. defer srv.Unlock()
  1025. switch kind {
  1026. case "pull":
  1027. if c, exists := srv.pullingPool[key]; exists {
  1028. close(c)
  1029. delete(srv.pullingPool, key)
  1030. }
  1031. case "push":
  1032. if c, exists := srv.pushingPool[key]; exists {
  1033. close(c)
  1034. delete(srv.pushingPool, key)
  1035. }
  1036. default:
  1037. return fmt.Errorf("Unknown pool type")
  1038. }
  1039. return nil
  1040. }
  1041. func (srv *Server) ImagePull(localName string, tag string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig, metaHeaders map[string][]string, parallel bool) error {
  1042. out = utils.NewWriteFlusher(out)
  1043. c, err := srv.poolAdd("pull", localName+":"+tag)
  1044. if err != nil {
  1045. if c != nil {
  1046. // Another pull of the same repository is already taking place; just wait for it to finish
  1047. out.Write(sf.FormatStatus("", "Repository %s already being pulled by another client. Waiting.", localName))
  1048. <-c
  1049. return nil
  1050. }
  1051. return err
  1052. }
  1053. defer srv.poolRemove("pull", localName+":"+tag)
  1054. // Resolve the Repository name from fqn to endpoint + name
  1055. endpoint, remoteName, err := registry.ResolveRepositoryName(localName)
  1056. if err != nil {
  1057. return err
  1058. }
  1059. r, err := registry.NewRegistry(authConfig, srv.HTTPRequestFactory(metaHeaders), endpoint)
  1060. if err != nil {
  1061. return err
  1062. }
  1063. if endpoint == auth.IndexServerAddress() {
  1064. // If pull "index.docker.io/foo/bar", it's stored locally under "foo/bar"
  1065. localName = remoteName
  1066. }
  1067. if err = srv.pullRepository(r, out, localName, remoteName, tag, sf, parallel); err != nil {
  1068. return err
  1069. }
  1070. return nil
  1071. }
  1072. // Retrieve the all the images to be uploaded in the correct order
  1073. // Note: we can't use a map as it is not ordered
  1074. func (srv *Server) getImageList(localRepo map[string]string) ([][]*registry.ImgData, error) {
  1075. imgList := map[string]*registry.ImgData{}
  1076. depGraph := utils.NewDependencyGraph()
  1077. for tag, id := range localRepo {
  1078. img, err := srv.runtime.graph.Get(id)
  1079. if err != nil {
  1080. return nil, err
  1081. }
  1082. depGraph.NewNode(img.ID)
  1083. img.WalkHistory(func(current *Image) error {
  1084. imgList[current.ID] = &registry.ImgData{
  1085. ID: current.ID,
  1086. Tag: tag,
  1087. }
  1088. parent, err := current.GetParent()
  1089. if err != nil {
  1090. return err
  1091. }
  1092. if parent == nil {
  1093. return nil
  1094. }
  1095. depGraph.NewNode(parent.ID)
  1096. depGraph.AddDependency(current.ID, parent.ID)
  1097. return nil
  1098. })
  1099. }
  1100. traversalMap, err := depGraph.GenerateTraversalMap()
  1101. if err != nil {
  1102. return nil, err
  1103. }
  1104. utils.Debugf("Traversal map: %v", traversalMap)
  1105. result := [][]*registry.ImgData{}
  1106. for _, round := range traversalMap {
  1107. dataRound := []*registry.ImgData{}
  1108. for _, imgID := range round {
  1109. dataRound = append(dataRound, imgList[imgID])
  1110. }
  1111. result = append(result, dataRound)
  1112. }
  1113. return result, nil
  1114. }
  1115. func flatten(slc [][]*registry.ImgData) []*registry.ImgData {
  1116. result := []*registry.ImgData{}
  1117. for _, x := range slc {
  1118. result = append(result, x...)
  1119. }
  1120. return result
  1121. }
  1122. func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, localName, remoteName string, localRepo map[string]string, sf *utils.StreamFormatter) error {
  1123. out = utils.NewWriteFlusher(out)
  1124. imgList, err := srv.getImageList(localRepo)
  1125. if err != nil {
  1126. return err
  1127. }
  1128. flattenedImgList := flatten(imgList)
  1129. out.Write(sf.FormatStatus("", "Sending image list"))
  1130. var repoData *registry.RepositoryData
  1131. repoData, err = r.PushImageJSONIndex(remoteName, flattenedImgList, false, nil)
  1132. if err != nil {
  1133. return err
  1134. }
  1135. for _, ep := range repoData.Endpoints {
  1136. out.Write(sf.FormatStatus("", "Pushing repository %s (%d tags)", localName, len(localRepo)))
  1137. // This section can not be parallelized (each round depends on the previous one)
  1138. for i, round := range imgList {
  1139. // FIXME: This section can be parallelized
  1140. for _, elem := range round {
  1141. var pushTags func() error
  1142. pushTags = func() error {
  1143. if i < (len(imgList) - 1) {
  1144. // Only tag the top layer in the repository
  1145. return nil
  1146. }
  1147. out.Write(sf.FormatStatus("", "Pushing tags for rev [%s] on {%s}", utils.TruncateID(elem.ID), ep+"repositories/"+remoteName+"/tags/"+elem.Tag))
  1148. if err := r.PushRegistryTag(remoteName, elem.ID, elem.Tag, ep, repoData.Tokens); err != nil {
  1149. return err
  1150. }
  1151. return nil
  1152. }
  1153. if _, exists := repoData.ImgList[elem.ID]; exists {
  1154. if err := pushTags(); err != nil {
  1155. return err
  1156. }
  1157. out.Write(sf.FormatProgress(utils.TruncateID(elem.ID), "Image already pushed, skipping", nil))
  1158. continue
  1159. } else if r.LookupRemoteImage(elem.ID, ep, repoData.Tokens) {
  1160. if err := pushTags(); err != nil {
  1161. return err
  1162. }
  1163. out.Write(sf.FormatProgress(utils.TruncateID(elem.ID), "Image already pushed, skipping", nil))
  1164. continue
  1165. }
  1166. checksum, err := srv.pushImage(r, out, remoteName, elem.ID, ep, repoData.Tokens, sf)
  1167. if err != nil {
  1168. // FIXME: Continue on error?
  1169. return err
  1170. }
  1171. elem.Checksum = checksum
  1172. if err := pushTags(); err != nil {
  1173. return err
  1174. }
  1175. }
  1176. }
  1177. }
  1178. if _, err := r.PushImageJSONIndex(remoteName, flattenedImgList, true, repoData.Endpoints); err != nil {
  1179. return err
  1180. }
  1181. return nil
  1182. }
  1183. func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgID, ep string, token []string, sf *utils.StreamFormatter) (checksum string, err error) {
  1184. out = utils.NewWriteFlusher(out)
  1185. jsonRaw, err := ioutil.ReadFile(path.Join(srv.runtime.graph.Root, imgID, "json"))
  1186. if err != nil {
  1187. return "", fmt.Errorf("Cannot retrieve the path for {%s}: %s", imgID, err)
  1188. }
  1189. out.Write(sf.FormatProgress(utils.TruncateID(imgID), "Pushing", nil))
  1190. imgData := &registry.ImgData{
  1191. ID: imgID,
  1192. }
  1193. // Send the json
  1194. if err := r.PushImageJSONRegistry(imgData, jsonRaw, ep, token); err != nil {
  1195. if err == registry.ErrAlreadyExists {
  1196. out.Write(sf.FormatProgress(utils.TruncateID(imgData.ID), "Image already pushed, skipping", nil))
  1197. return "", nil
  1198. }
  1199. return "", err
  1200. }
  1201. layerData, err := srv.runtime.graph.TempLayerArchive(imgID, archive.Uncompressed, sf, out)
  1202. if err != nil {
  1203. return "", fmt.Errorf("Failed to generate layer archive: %s", err)
  1204. }
  1205. defer os.RemoveAll(layerData.Name())
  1206. // Send the layer
  1207. checksum, err = r.PushImageLayerRegistry(imgData.ID, utils.ProgressReader(layerData, int(layerData.Size), out, sf, false, utils.TruncateID(imgData.ID), "Pushing"), ep, token, jsonRaw)
  1208. if err != nil {
  1209. return "", err
  1210. }
  1211. imgData.Checksum = checksum
  1212. // Send the checksum
  1213. if err := r.PushImageChecksumRegistry(imgData, ep, token); err != nil {
  1214. return "", err
  1215. }
  1216. out.Write(sf.FormatProgress(utils.TruncateID(imgData.ID), "Image successfully pushed", nil))
  1217. return imgData.Checksum, nil
  1218. }
  1219. // FIXME: Allow to interrupt current push when new push of same image is done.
  1220. func (srv *Server) ImagePush(localName string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig, metaHeaders map[string][]string) error {
  1221. if _, err := srv.poolAdd("push", localName); err != nil {
  1222. return err
  1223. }
  1224. defer srv.poolRemove("push", localName)
  1225. // Resolve the Repository name from fqn to endpoint + name
  1226. endpoint, remoteName, err := registry.ResolveRepositoryName(localName)
  1227. if err != nil {
  1228. return err
  1229. }
  1230. out = utils.NewWriteFlusher(out)
  1231. img, err := srv.runtime.graph.Get(localName)
  1232. r, err2 := registry.NewRegistry(authConfig, srv.HTTPRequestFactory(metaHeaders), endpoint)
  1233. if err2 != nil {
  1234. return err2
  1235. }
  1236. if err != nil {
  1237. reposLen := len(srv.runtime.repositories.Repositories[localName])
  1238. out.Write(sf.FormatStatus("", "The push refers to a repository [%s] (len: %d)", localName, reposLen))
  1239. // If it fails, try to get the repository
  1240. if localRepo, exists := srv.runtime.repositories.Repositories[localName]; exists {
  1241. if err := srv.pushRepository(r, out, localName, remoteName, localRepo, sf); err != nil {
  1242. return err
  1243. }
  1244. return nil
  1245. }
  1246. return err
  1247. }
  1248. var token []string
  1249. out.Write(sf.FormatStatus("", "The push refers to an image: [%s]", localName))
  1250. if _, err := srv.pushImage(r, out, remoteName, img.ID, endpoint, token, sf); err != nil {
  1251. return err
  1252. }
  1253. return nil
  1254. }
  1255. func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Writer, sf *utils.StreamFormatter) error {
  1256. var archive io.Reader
  1257. var resp *http.Response
  1258. if src == "-" {
  1259. archive = in
  1260. } else {
  1261. u, err := url.Parse(src)
  1262. if err != nil {
  1263. return err
  1264. }
  1265. if u.Scheme == "" {
  1266. u.Scheme = "http"
  1267. u.Host = src
  1268. u.Path = ""
  1269. }
  1270. out.Write(sf.FormatStatus("", "Downloading from %s", u))
  1271. // Download with curl (pretty progress bar)
  1272. // If curl is not available, fallback to http.Get()
  1273. resp, err = utils.Download(u.String())
  1274. if err != nil {
  1275. return err
  1276. }
  1277. archive = utils.ProgressReader(resp.Body, int(resp.ContentLength), out, sf, true, "", "Importing")
  1278. }
  1279. img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src, "", nil)
  1280. if err != nil {
  1281. return err
  1282. }
  1283. // Optionally register the image at REPO/TAG
  1284. if repo != "" {
  1285. if err := srv.runtime.repositories.Set(repo, tag, img.ID, true); err != nil {
  1286. return err
  1287. }
  1288. }
  1289. out.Write(sf.FormatStatus("", img.ID))
  1290. return nil
  1291. }
  1292. func (srv *Server) ContainerCreate(job *engine.Job) engine.Status {
  1293. var name string
  1294. if len(job.Args) == 1 {
  1295. name = job.Args[0]
  1296. } else if len(job.Args) > 1 {
  1297. job.Printf("Usage: %s", job.Name)
  1298. return engine.StatusErr
  1299. }
  1300. var config Config
  1301. if err := job.ExportEnv(&config); err != nil {
  1302. job.Error(err)
  1303. return engine.StatusErr
  1304. }
  1305. if config.Memory != 0 && config.Memory < 524288 {
  1306. job.Errorf("Minimum memory limit allowed is 512k")
  1307. return engine.StatusErr
  1308. }
  1309. if config.Memory > 0 && !srv.runtime.capabilities.MemoryLimit {
  1310. config.Memory = 0
  1311. }
  1312. if config.Memory > 0 && !srv.runtime.capabilities.SwapLimit {
  1313. config.MemorySwap = -1
  1314. }
  1315. container, buildWarnings, err := srv.runtime.Create(&config, name)
  1316. if err != nil {
  1317. if srv.runtime.graph.IsNotExist(err) {
  1318. _, tag := utils.ParseRepositoryTag(config.Image)
  1319. if tag == "" {
  1320. tag = DEFAULTTAG
  1321. }
  1322. job.Errorf("No such image: %s (tag: %s)", config.Image, tag)
  1323. return engine.StatusErr
  1324. }
  1325. job.Error(err)
  1326. return engine.StatusErr
  1327. }
  1328. srv.LogEvent("create", container.ID, srv.runtime.repositories.ImageName(container.Image))
  1329. // FIXME: this is necessary because runtime.Create might return a nil container
  1330. // with a non-nil error. This should not happen! Once it's fixed we
  1331. // can remove this workaround.
  1332. if container != nil {
  1333. job.Printf("%s\n", container.ID)
  1334. }
  1335. for _, warning := range buildWarnings {
  1336. job.Errorf("%s\n", warning)
  1337. }
  1338. return engine.StatusOK
  1339. }
  1340. func (srv *Server) ContainerRestart(job *engine.Job) engine.Status {
  1341. if len(job.Args) != 1 {
  1342. job.Errorf("Usage: %s CONTAINER\n", job.Name)
  1343. return engine.StatusErr
  1344. }
  1345. name := job.Args[0]
  1346. t := job.GetenvInt("t")
  1347. if t == -1 {
  1348. t = 10
  1349. }
  1350. if container := srv.runtime.Get(name); container != nil {
  1351. if err := container.Restart(int(t)); err != nil {
  1352. job.Errorf("Cannot restart container %s: %s\n", name, err)
  1353. return engine.StatusErr
  1354. }
  1355. srv.LogEvent("restart", container.ID, srv.runtime.repositories.ImageName(container.Image))
  1356. } else {
  1357. job.Errorf("No such container: %s\n", name)
  1358. return engine.StatusErr
  1359. }
  1360. return engine.StatusOK
  1361. }
  1362. func (srv *Server) ContainerDestroy(job *engine.Job) engine.Status {
  1363. if len(job.Args) != 1 {
  1364. job.Errorf("Not enough arguments. Usage: %s CONTAINER\n", job.Name)
  1365. return engine.StatusErr
  1366. }
  1367. name := job.Args[0]
  1368. removeVolume := job.GetenvBool("removeVolume")
  1369. removeLink := job.GetenvBool("removeLink")
  1370. container := srv.runtime.Get(name)
  1371. if removeLink {
  1372. if container == nil {
  1373. job.Errorf("No such link: %s", name)
  1374. return engine.StatusErr
  1375. }
  1376. name, err := getFullName(name)
  1377. if err != nil {
  1378. job.Error(err)
  1379. return engine.StatusErr
  1380. }
  1381. parent, n := path.Split(name)
  1382. if parent == "/" {
  1383. job.Errorf("Conflict, cannot remove the default name of the container")
  1384. return engine.StatusErr
  1385. }
  1386. pe := srv.runtime.containerGraph.Get(parent)
  1387. if pe == nil {
  1388. job.Errorf("Cannot get parent %s for name %s", parent, name)
  1389. return engine.StatusErr
  1390. }
  1391. parentContainer := srv.runtime.Get(pe.ID())
  1392. if parentContainer != nil && parentContainer.activeLinks != nil {
  1393. if link, exists := parentContainer.activeLinks[n]; exists {
  1394. link.Disable()
  1395. } else {
  1396. utils.Debugf("Could not find active link for %s", name)
  1397. }
  1398. }
  1399. if err := srv.runtime.containerGraph.Delete(name); err != nil {
  1400. job.Error(err)
  1401. return engine.StatusErr
  1402. }
  1403. return engine.StatusOK
  1404. }
  1405. if container != nil {
  1406. if container.State.IsRunning() {
  1407. job.Errorf("Impossible to remove a running container, please stop it first")
  1408. return engine.StatusErr
  1409. }
  1410. volumes := make(map[string]struct{})
  1411. binds := make(map[string]struct{})
  1412. for _, bind := range container.hostConfig.Binds {
  1413. splitBind := strings.Split(bind, ":")
  1414. source := splitBind[0]
  1415. binds[source] = struct{}{}
  1416. }
  1417. // Store all the deleted containers volumes
  1418. for _, volumeId := range container.Volumes {
  1419. // Skip the volumes mounted from external
  1420. if _, exists := binds[volumeId]; exists {
  1421. continue
  1422. }
  1423. volumeId = strings.TrimSuffix(volumeId, "/layer")
  1424. volumeId = filepath.Base(volumeId)
  1425. volumes[volumeId] = struct{}{}
  1426. }
  1427. if err := srv.runtime.Destroy(container); err != nil {
  1428. job.Errorf("Cannot destroy container %s: %s", name, err)
  1429. return engine.StatusErr
  1430. }
  1431. srv.LogEvent("destroy", container.ID, srv.runtime.repositories.ImageName(container.Image))
  1432. if removeVolume {
  1433. // Retrieve all volumes from all remaining containers
  1434. usedVolumes := make(map[string]*Container)
  1435. for _, container := range srv.runtime.List() {
  1436. for _, containerVolumeId := range container.Volumes {
  1437. usedVolumes[containerVolumeId] = container
  1438. }
  1439. }
  1440. for volumeId := range volumes {
  1441. // If the requested volu
  1442. if c, exists := usedVolumes[volumeId]; exists {
  1443. log.Printf("The volume %s is used by the container %s. Impossible to remove it. Skipping.\n", volumeId, c.ID)
  1444. continue
  1445. }
  1446. if err := srv.runtime.volumes.Delete(volumeId); err != nil {
  1447. job.Error(err)
  1448. return engine.StatusErr
  1449. }
  1450. }
  1451. }
  1452. } else {
  1453. job.Errorf("No such container: %s", name)
  1454. return engine.StatusErr
  1455. }
  1456. return engine.StatusOK
  1457. }
  1458. var ErrImageReferenced = errors.New("Image referenced by a repository")
  1459. func (srv *Server) deleteImageAndChildren(id string, imgs *[]APIRmi, byParents map[string][]*Image) error {
  1460. // If the image is referenced by a repo, do not delete
  1461. if len(srv.runtime.repositories.ByID()[id]) != 0 {
  1462. return ErrImageReferenced
  1463. }
  1464. // If the image is not referenced but has children, go recursive
  1465. referenced := false
  1466. for _, img := range byParents[id] {
  1467. if err := srv.deleteImageAndChildren(img.ID, imgs, byParents); err != nil {
  1468. if err != ErrImageReferenced {
  1469. return err
  1470. }
  1471. referenced = true
  1472. }
  1473. }
  1474. if referenced {
  1475. return ErrImageReferenced
  1476. }
  1477. // If the image is not referenced and has no children, remove it
  1478. byParents, err := srv.runtime.graph.ByParent()
  1479. if err != nil {
  1480. return err
  1481. }
  1482. if len(byParents[id]) == 0 && srv.canDeleteImage(id) == nil {
  1483. if err := srv.runtime.repositories.DeleteAll(id); err != nil {
  1484. return err
  1485. }
  1486. err := srv.runtime.graph.Delete(id)
  1487. if err != nil {
  1488. return err
  1489. }
  1490. *imgs = append(*imgs, APIRmi{Deleted: id})
  1491. srv.LogEvent("delete", id, "")
  1492. return nil
  1493. }
  1494. return nil
  1495. }
  1496. func (srv *Server) deleteImageParents(img *Image, imgs *[]APIRmi) error {
  1497. if img.Parent != "" {
  1498. parent, err := srv.runtime.graph.Get(img.Parent)
  1499. if err != nil {
  1500. return err
  1501. }
  1502. byParents, err := srv.runtime.graph.ByParent()
  1503. if err != nil {
  1504. return err
  1505. }
  1506. // Remove all children images
  1507. if err := srv.deleteImageAndChildren(img.Parent, imgs, byParents); err != nil {
  1508. return err
  1509. }
  1510. return srv.deleteImageParents(parent, imgs)
  1511. }
  1512. return nil
  1513. }
  1514. func (srv *Server) deleteImage(img *Image, repoName, tag string) ([]APIRmi, error) {
  1515. var (
  1516. imgs = []APIRmi{}
  1517. tags = []string{}
  1518. )
  1519. //If delete by id, see if the id belong only to one repository
  1520. if repoName == "" {
  1521. for _, repoAndTag := range srv.runtime.repositories.ByID()[img.ID] {
  1522. parsedRepo, parsedTag := utils.ParseRepositoryTag(repoAndTag)
  1523. if repoName == "" || repoName == parsedRepo {
  1524. repoName = parsedRepo
  1525. if parsedTag != "" {
  1526. tags = append(tags, parsedTag)
  1527. }
  1528. } else if repoName != parsedRepo {
  1529. // the id belongs to multiple repos, like base:latest and user:test,
  1530. // in that case return conflict
  1531. return nil, fmt.Errorf("Conflict, cannot delete image %s because it is tagged in multiple repositories", utils.TruncateID(img.ID))
  1532. }
  1533. }
  1534. } else {
  1535. tags = append(tags, tag)
  1536. }
  1537. //Untag the current image
  1538. for _, tag := range tags {
  1539. tagDeleted, err := srv.runtime.repositories.Delete(repoName, tag)
  1540. if err != nil {
  1541. return nil, err
  1542. }
  1543. if tagDeleted {
  1544. imgs = append(imgs, APIRmi{Untagged: img.ID})
  1545. srv.LogEvent("untag", img.ID, "")
  1546. }
  1547. }
  1548. if len(srv.runtime.repositories.ByID()[img.ID]) == 0 {
  1549. if err := srv.deleteImageAndChildren(img.ID, &imgs, nil); err != nil {
  1550. if err != ErrImageReferenced {
  1551. return imgs, err
  1552. }
  1553. } else if err := srv.deleteImageParents(img, &imgs); err != nil {
  1554. if err != ErrImageReferenced {
  1555. return imgs, err
  1556. }
  1557. }
  1558. }
  1559. return imgs, nil
  1560. }
  1561. func (srv *Server) ImageDelete(name string, autoPrune bool) ([]APIRmi, error) {
  1562. var (
  1563. repository, tag string
  1564. img, err = srv.runtime.repositories.LookupImage(name)
  1565. )
  1566. if err != nil {
  1567. return nil, fmt.Errorf("No such image: %s", name)
  1568. }
  1569. // FIXME: What does autoPrune mean ?
  1570. if !autoPrune {
  1571. if err := srv.runtime.graph.Delete(img.ID); err != nil {
  1572. return nil, fmt.Errorf("Cannot delete image %s: %s", name, err)
  1573. }
  1574. return nil, nil
  1575. }
  1576. if !strings.Contains(img.ID, name) {
  1577. repository, tag = utils.ParseRepositoryTag(name)
  1578. }
  1579. // If we have a repo and the image is not referenced anywhere else
  1580. // then just perform an untag and do not validate.
  1581. //
  1582. // i.e. only validate if we are performing an actual delete and not
  1583. // an untag op
  1584. if repository != "" && len(srv.runtime.repositories.ByID()[img.ID]) == 1 {
  1585. // Prevent deletion if image is used by a container
  1586. if err := srv.canDeleteImage(img.ID); err != nil {
  1587. return nil, err
  1588. }
  1589. }
  1590. return srv.deleteImage(img, repository, tag)
  1591. }
  1592. func (srv *Server) canDeleteImage(imgID string) error {
  1593. for _, container := range srv.runtime.List() {
  1594. parent, err := srv.runtime.repositories.LookupImage(container.Image)
  1595. if err != nil {
  1596. return err
  1597. }
  1598. if err := parent.WalkHistory(func(p *Image) error {
  1599. if imgID == p.ID {
  1600. return fmt.Errorf("Conflict, cannot delete %s because the container %s is using it", utils.TruncateID(imgID), utils.TruncateID(container.ID))
  1601. }
  1602. return nil
  1603. }); err != nil {
  1604. return err
  1605. }
  1606. }
  1607. return nil
  1608. }
  1609. func (srv *Server) ImageGetCached(imgID string, config *Config) (*Image, error) {
  1610. // Retrieve all images
  1611. images, err := srv.runtime.graph.Map()
  1612. if err != nil {
  1613. return nil, err
  1614. }
  1615. // Store the tree in a map of map (map[parentId][childId])
  1616. imageMap := make(map[string]map[string]struct{})
  1617. for _, img := range images {
  1618. if _, exists := imageMap[img.Parent]; !exists {
  1619. imageMap[img.Parent] = make(map[string]struct{})
  1620. }
  1621. imageMap[img.Parent][img.ID] = struct{}{}
  1622. }
  1623. // Loop on the children of the given image and check the config
  1624. var match *Image
  1625. for elem := range imageMap[imgID] {
  1626. img, err := srv.runtime.graph.Get(elem)
  1627. if err != nil {
  1628. return nil, err
  1629. }
  1630. if CompareConfig(&img.ContainerConfig, config) {
  1631. if match == nil || match.Created.Before(img.Created) {
  1632. match = img
  1633. }
  1634. }
  1635. }
  1636. return match, nil
  1637. }
  1638. func (srv *Server) RegisterLinks(container *Container, hostConfig *HostConfig) error {
  1639. runtime := srv.runtime
  1640. if hostConfig != nil && hostConfig.Links != nil {
  1641. for _, l := range hostConfig.Links {
  1642. parts, err := parseLink(l)
  1643. if err != nil {
  1644. return err
  1645. }
  1646. child, err := srv.runtime.GetByName(parts["name"])
  1647. if err != nil {
  1648. return err
  1649. }
  1650. if child == nil {
  1651. return fmt.Errorf("Could not get container for %s", parts["name"])
  1652. }
  1653. if err := runtime.RegisterLink(container, child, parts["alias"]); err != nil {
  1654. return err
  1655. }
  1656. }
  1657. // After we load all the links into the runtime
  1658. // set them to nil on the hostconfig
  1659. hostConfig.Links = nil
  1660. if err := container.writeHostConfig(); err != nil {
  1661. return err
  1662. }
  1663. }
  1664. return nil
  1665. }
  1666. func (srv *Server) ContainerStart(job *engine.Job) engine.Status {
  1667. if len(job.Args) < 1 {
  1668. job.Errorf("Usage: %s container_id", job.Name)
  1669. return engine.StatusErr
  1670. }
  1671. name := job.Args[0]
  1672. runtime := srv.runtime
  1673. container := runtime.Get(name)
  1674. if container == nil {
  1675. job.Errorf("No such container: %s", name)
  1676. return engine.StatusErr
  1677. }
  1678. // If no environment was set, then no hostconfig was passed.
  1679. if len(job.Environ()) > 0 {
  1680. var hostConfig HostConfig
  1681. if err := job.ExportEnv(&hostConfig); err != nil {
  1682. job.Error(err)
  1683. return engine.StatusErr
  1684. }
  1685. // Validate the HostConfig binds. Make sure that:
  1686. // 1) the source of a bind mount isn't /
  1687. // The bind mount "/:/foo" isn't allowed.
  1688. // 2) Check that the source exists
  1689. // The source to be bind mounted must exist.
  1690. for _, bind := range hostConfig.Binds {
  1691. splitBind := strings.Split(bind, ":")
  1692. source := splitBind[0]
  1693. // refuse to bind mount "/" to the container
  1694. if source == "/" {
  1695. job.Errorf("Invalid bind mount '%s' : source can't be '/'", bind)
  1696. return engine.StatusErr
  1697. }
  1698. // ensure the source exists on the host
  1699. _, err := os.Stat(source)
  1700. if err != nil && os.IsNotExist(err) {
  1701. job.Errorf("Invalid bind mount '%s' : source doesn't exist", bind)
  1702. return engine.StatusErr
  1703. }
  1704. }
  1705. // Register any links from the host config before starting the container
  1706. if err := srv.RegisterLinks(container, &hostConfig); err != nil {
  1707. job.Error(err)
  1708. return engine.StatusErr
  1709. }
  1710. container.hostConfig = &hostConfig
  1711. container.ToDisk()
  1712. }
  1713. if err := container.Start(); err != nil {
  1714. job.Errorf("Cannot start container %s: %s", name, err)
  1715. return engine.StatusErr
  1716. }
  1717. srv.LogEvent("start", container.ID, runtime.repositories.ImageName(container.Image))
  1718. return engine.StatusOK
  1719. }
  1720. func (srv *Server) ContainerStop(job *engine.Job) engine.Status {
  1721. if len(job.Args) != 1 {
  1722. job.Errorf("Usage: %s CONTAINER\n", job.Name)
  1723. return engine.StatusErr
  1724. }
  1725. name := job.Args[0]
  1726. t := job.GetenvInt("t")
  1727. if t == -1 {
  1728. t = 10
  1729. }
  1730. if container := srv.runtime.Get(name); container != nil {
  1731. if err := container.Stop(int(t)); err != nil {
  1732. job.Errorf("Cannot stop container %s: %s\n", name, err)
  1733. return engine.StatusErr
  1734. }
  1735. srv.LogEvent("stop", container.ID, srv.runtime.repositories.ImageName(container.Image))
  1736. } else {
  1737. job.Errorf("No such container: %s\n", name)
  1738. return engine.StatusErr
  1739. }
  1740. return engine.StatusOK
  1741. }
  1742. func (srv *Server) ContainerWait(job *engine.Job) engine.Status {
  1743. if len(job.Args) != 1 {
  1744. job.Errorf("Usage: %s", job.Name)
  1745. return engine.StatusErr
  1746. }
  1747. name := job.Args[0]
  1748. if container := srv.runtime.Get(name); container != nil {
  1749. status := container.Wait()
  1750. job.Printf("%d\n", status)
  1751. return engine.StatusOK
  1752. }
  1753. job.Errorf("%s: no such container: %s", job.Name, name)
  1754. return engine.StatusErr
  1755. }
  1756. func (srv *Server) ContainerResize(job *engine.Job) engine.Status {
  1757. if len(job.Args) != 3 {
  1758. job.Errorf("Not enough arguments. Usage: %s CONTAINER HEIGHT WIDTH\n", job.Name)
  1759. return engine.StatusErr
  1760. }
  1761. name := job.Args[0]
  1762. height, err := strconv.Atoi(job.Args[1])
  1763. if err != nil {
  1764. job.Error(err)
  1765. return engine.StatusErr
  1766. }
  1767. width, err := strconv.Atoi(job.Args[2])
  1768. if err != nil {
  1769. job.Error(err)
  1770. return engine.StatusErr
  1771. }
  1772. if container := srv.runtime.Get(name); container != nil {
  1773. if err := container.Resize(height, width); err != nil {
  1774. job.Error(err)
  1775. return engine.StatusErr
  1776. }
  1777. return engine.StatusOK
  1778. }
  1779. job.Errorf("No such container: %s", name)
  1780. return engine.StatusErr
  1781. }
  1782. func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, stderr bool, inStream io.ReadCloser, outStream, errStream io.Writer) error {
  1783. container := srv.runtime.Get(name)
  1784. if container == nil {
  1785. return fmt.Errorf("No such container: %s", name)
  1786. }
  1787. //logs
  1788. if logs {
  1789. cLog, err := container.ReadLog("json")
  1790. if err != nil && os.IsNotExist(err) {
  1791. // Legacy logs
  1792. utils.Errorf("Old logs format")
  1793. if stdout {
  1794. cLog, err := container.ReadLog("stdout")
  1795. if err != nil {
  1796. utils.Errorf("Error reading logs (stdout): %s", err)
  1797. } else if _, err := io.Copy(outStream, cLog); err != nil {
  1798. utils.Errorf("Error streaming logs (stdout): %s", err)
  1799. }
  1800. }
  1801. if stderr {
  1802. cLog, err := container.ReadLog("stderr")
  1803. if err != nil {
  1804. utils.Errorf("Error reading logs (stderr): %s", err)
  1805. } else if _, err := io.Copy(errStream, cLog); err != nil {
  1806. utils.Errorf("Error streaming logs (stderr): %s", err)
  1807. }
  1808. }
  1809. } else if err != nil {
  1810. utils.Errorf("Error reading logs (json): %s", err)
  1811. } else {
  1812. dec := json.NewDecoder(cLog)
  1813. for {
  1814. l := &utils.JSONLog{}
  1815. if err := dec.Decode(l); err == io.EOF {
  1816. break
  1817. } else if err != nil {
  1818. utils.Errorf("Error streaming logs: %s", err)
  1819. break
  1820. }
  1821. if l.Stream == "stdout" && stdout {
  1822. fmt.Fprintf(outStream, "%s", l.Log)
  1823. }
  1824. if l.Stream == "stderr" && stderr {
  1825. fmt.Fprintf(errStream, "%s", l.Log)
  1826. }
  1827. }
  1828. }
  1829. }
  1830. //stream
  1831. if stream {
  1832. if container.State.IsGhost() {
  1833. return fmt.Errorf("Impossible to attach to a ghost container")
  1834. }
  1835. var (
  1836. cStdin io.ReadCloser
  1837. cStdout, cStderr io.Writer
  1838. cStdinCloser io.Closer
  1839. )
  1840. if stdin {
  1841. r, w := io.Pipe()
  1842. go func() {
  1843. defer w.Close()
  1844. defer utils.Debugf("Closing buffered stdin pipe")
  1845. io.Copy(w, inStream)
  1846. }()
  1847. cStdin = r
  1848. cStdinCloser = inStream
  1849. }
  1850. if stdout {
  1851. cStdout = outStream
  1852. }
  1853. if stderr {
  1854. cStderr = errStream
  1855. }
  1856. <-container.Attach(cStdin, cStdinCloser, cStdout, cStderr)
  1857. // If we are in stdinonce mode, wait for the process to end
  1858. // otherwise, simply return
  1859. if container.Config.StdinOnce && !container.Config.Tty {
  1860. container.Wait()
  1861. }
  1862. }
  1863. return nil
  1864. }
  1865. func (srv *Server) ContainerInspect(name string) (*Container, error) {
  1866. if container := srv.runtime.Get(name); container != nil {
  1867. return container, nil
  1868. }
  1869. return nil, fmt.Errorf("No such container: %s", name)
  1870. }
  1871. func (srv *Server) ImageInspect(name string) (*Image, error) {
  1872. if image, err := srv.runtime.repositories.LookupImage(name); err == nil && image != nil {
  1873. return image, nil
  1874. }
  1875. return nil, fmt.Errorf("No such image: %s", name)
  1876. }
  1877. func (srv *Server) ContainerCopy(job *engine.Job) engine.Status {
  1878. if len(job.Args) != 2 {
  1879. job.Errorf("Usage: %s CONTAINER RESOURCE\n", job.Name)
  1880. return engine.StatusErr
  1881. }
  1882. var (
  1883. name = job.Args[0]
  1884. resource = job.Args[1]
  1885. )
  1886. if container := srv.runtime.Get(name); container != nil {
  1887. data, err := container.Copy(resource)
  1888. if err != nil {
  1889. job.Error(err)
  1890. return engine.StatusErr
  1891. }
  1892. if _, err := io.Copy(job.Stdout, data); err != nil {
  1893. job.Error(err)
  1894. return engine.StatusErr
  1895. }
  1896. return engine.StatusOK
  1897. }
  1898. job.Errorf("No such container: %s", name)
  1899. return engine.StatusErr
  1900. }
  1901. func NewServer(eng *engine.Engine, config *DaemonConfig) (*Server, error) {
  1902. runtime, err := NewRuntime(config)
  1903. if err != nil {
  1904. return nil, err
  1905. }
  1906. srv := &Server{
  1907. Eng: eng,
  1908. runtime: runtime,
  1909. pullingPool: make(map[string]chan struct{}),
  1910. pushingPool: make(map[string]chan struct{}),
  1911. events: make([]utils.JSONMessage, 0, 64), //only keeps the 64 last events
  1912. listeners: make(map[string]chan utils.JSONMessage),
  1913. }
  1914. runtime.srv = srv
  1915. return srv, nil
  1916. }
  1917. func (srv *Server) HTTPRequestFactory(metaHeaders map[string][]string) *utils.HTTPRequestFactory {
  1918. srv.Lock()
  1919. defer srv.Unlock()
  1920. v := dockerVersion()
  1921. httpVersion := make([]utils.VersionInfo, 0, 4)
  1922. httpVersion = append(httpVersion, &simpleVersionInfo{"docker", v.Get("Version")})
  1923. httpVersion = append(httpVersion, &simpleVersionInfo{"go", v.Get("GoVersion")})
  1924. httpVersion = append(httpVersion, &simpleVersionInfo{"git-commit", v.Get("GitCommit")})
  1925. httpVersion = append(httpVersion, &simpleVersionInfo{"kernel", v.Get("KernelVersion")})
  1926. httpVersion = append(httpVersion, &simpleVersionInfo{"os", v.Get("Os")})
  1927. httpVersion = append(httpVersion, &simpleVersionInfo{"arch", v.Get("Arch")})
  1928. ud := utils.NewHTTPUserAgentDecorator(httpVersion...)
  1929. md := &utils.HTTPMetaHeadersDecorator{
  1930. Headers: metaHeaders,
  1931. }
  1932. factory := utils.NewHTTPRequestFactory(ud, md)
  1933. return factory
  1934. }
  1935. func (srv *Server) LogEvent(action, id, from string) *utils.JSONMessage {
  1936. now := time.Now().UTC().Unix()
  1937. jm := utils.JSONMessage{Status: action, ID: id, From: from, Time: now}
  1938. srv.AddEvent(jm)
  1939. for _, c := range srv.listeners {
  1940. select { // non blocking channel
  1941. case c <- jm:
  1942. default:
  1943. }
  1944. }
  1945. return &jm
  1946. }
  1947. func (srv *Server) AddEvent(jm utils.JSONMessage) {
  1948. srv.Lock()
  1949. defer srv.Unlock()
  1950. srv.events = append(srv.events, jm)
  1951. }
  1952. func (srv *Server) GetEvents() []utils.JSONMessage {
  1953. srv.RLock()
  1954. defer srv.RUnlock()
  1955. return srv.events
  1956. }
  1957. type Server struct {
  1958. sync.RWMutex
  1959. runtime *Runtime
  1960. pullingPool map[string]chan struct{}
  1961. pushingPool map[string]chan struct{}
  1962. events []utils.JSONMessage
  1963. listeners map[string]chan utils.JSONMessage
  1964. Eng *engine.Engine
  1965. }