server.go 60 KB

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