server.go 59 KB

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