server.go 71 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538
  1. // DEPRECATION NOTICE. PLEASE DO NOT ADD ANYTHING TO THIS FILE.
  2. //
  3. // server/server.go is deprecated. We are working on breaking it up into smaller, cleaner
  4. // pieces which will be easier to find and test. This will help make the code less
  5. // redundant and more readable.
  6. //
  7. // Contributors, please don't add anything to server/server.go, unless it has the explicit
  8. // goal of helping the deprecation effort.
  9. //
  10. // Maintainers, please refuse patches which add code to server/server.go.
  11. //
  12. // Instead try the following files:
  13. // * For code related to local image management, try graph/
  14. // * For code related to image downloading, uploading, remote search etc, try registry/
  15. // * For code related to the docker daemon, try daemon/
  16. // * For small utilities which could potentially be useful outside of Docker, try pkg/
  17. // * For miscalleneous "util" functions which are docker-specific, try encapsulating them
  18. // inside one of the subsystems above. If you really think they should be more widely
  19. // available, are you sure you can't remove the docker dependencies and move them to
  20. // pkg? In last resort, you can add them to utils/ (but please try not to).
  21. package server
  22. import (
  23. "encoding/json"
  24. "fmt"
  25. "io"
  26. "io/ioutil"
  27. "log"
  28. "net/http"
  29. "net/url"
  30. "os"
  31. "os/exec"
  32. gosignal "os/signal"
  33. "path"
  34. "path/filepath"
  35. "runtime"
  36. "strconv"
  37. "strings"
  38. "sync"
  39. "syscall"
  40. "time"
  41. "github.com/dotcloud/docker/api"
  42. "github.com/dotcloud/docker/archive"
  43. "github.com/dotcloud/docker/daemon"
  44. "github.com/dotcloud/docker/daemonconfig"
  45. "github.com/dotcloud/docker/dockerversion"
  46. "github.com/dotcloud/docker/engine"
  47. "github.com/dotcloud/docker/graph"
  48. "github.com/dotcloud/docker/image"
  49. "github.com/dotcloud/docker/pkg/graphdb"
  50. "github.com/dotcloud/docker/pkg/signal"
  51. "github.com/dotcloud/docker/registry"
  52. "github.com/dotcloud/docker/runconfig"
  53. "github.com/dotcloud/docker/utils"
  54. )
  55. // jobInitApi runs the remote api server `srv` as a daemon,
  56. // Only one api server can run at the same time - this is enforced by a pidfile.
  57. // The signals SIGINT, SIGQUIT and SIGTERM are intercepted for cleanup.
  58. func InitServer(job *engine.Job) engine.Status {
  59. job.Logf("Creating server")
  60. srv, err := NewServer(job.Eng, daemonconfig.ConfigFromJob(job))
  61. if err != nil {
  62. return job.Error(err)
  63. }
  64. if srv.daemon.Config().Pidfile != "" {
  65. job.Logf("Creating pidfile")
  66. if err := utils.CreatePidFile(srv.daemon.Config().Pidfile); err != nil {
  67. // FIXME: do we need fatal here instead of returning a job error?
  68. log.Fatal(err)
  69. }
  70. }
  71. job.Logf("Setting up signal traps")
  72. c := make(chan os.Signal, 1)
  73. gosignal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
  74. go func() {
  75. interruptCount := 0
  76. for sig := range c {
  77. go func() {
  78. log.Printf("Received signal '%v', starting shutdown of docker...\n", sig)
  79. switch sig {
  80. case os.Interrupt, syscall.SIGTERM:
  81. // If the user really wants to interrupt, let him do so.
  82. if interruptCount < 3 {
  83. interruptCount++
  84. // Initiate the cleanup only once
  85. if interruptCount == 1 {
  86. utils.RemovePidFile(srv.daemon.Config().Pidfile)
  87. srv.Close()
  88. } else {
  89. return
  90. }
  91. } else {
  92. log.Printf("Force shutdown of docker, interrupting cleanup\n")
  93. }
  94. case syscall.SIGQUIT:
  95. }
  96. os.Exit(128 + int(sig.(syscall.Signal)))
  97. }()
  98. }
  99. }()
  100. job.Eng.Hack_SetGlobalVar("httpapi.server", srv)
  101. job.Eng.Hack_SetGlobalVar("httpapi.daemon", srv.daemon)
  102. // FIXME: 'insert' is deprecated and should be removed in a future version.
  103. for name, handler := range map[string]engine.Handler{
  104. "export": srv.ContainerExport,
  105. "create": srv.ContainerCreate,
  106. "stop": srv.ContainerStop,
  107. "restart": srv.ContainerRestart,
  108. "start": srv.ContainerStart,
  109. "kill": srv.ContainerKill,
  110. "wait": srv.ContainerWait,
  111. "tag": srv.ImageTag,
  112. "resize": srv.ContainerResize,
  113. "commit": srv.ContainerCommit,
  114. "info": srv.DockerInfo,
  115. "container_delete": srv.ContainerDestroy,
  116. "image_export": srv.ImageExport,
  117. "images": srv.Images,
  118. "history": srv.ImageHistory,
  119. "viz": srv.ImagesViz,
  120. "container_copy": srv.ContainerCopy,
  121. "insert": srv.ImageInsert,
  122. "attach": srv.ContainerAttach,
  123. "logs": srv.ContainerLogs,
  124. "changes": srv.ContainerChanges,
  125. "top": srv.ContainerTop,
  126. "version": srv.DockerVersion,
  127. "load": srv.ImageLoad,
  128. "build": srv.Build,
  129. "pull": srv.ImagePull,
  130. "import": srv.ImageImport,
  131. "image_delete": srv.ImageDelete,
  132. "inspect": srv.JobInspect,
  133. "events": srv.Events,
  134. "push": srv.ImagePush,
  135. "containers": srv.Containers,
  136. } {
  137. if err := job.Eng.Register(name, handler); err != nil {
  138. return job.Error(err)
  139. }
  140. }
  141. return engine.StatusOK
  142. }
  143. // ContainerKill send signal to the container
  144. // If no signal is given (sig 0), then Kill with SIGKILL and wait
  145. // for the container to exit.
  146. // If a signal is given, then just send it to the container and return.
  147. func (srv *Server) ContainerKill(job *engine.Job) engine.Status {
  148. if n := len(job.Args); n < 1 || n > 2 {
  149. return job.Errorf("Usage: %s CONTAINER [SIGNAL]", job.Name)
  150. }
  151. var (
  152. name = job.Args[0]
  153. sig uint64
  154. err error
  155. )
  156. // If we have a signal, look at it. Otherwise, do nothing
  157. if len(job.Args) == 2 && job.Args[1] != "" {
  158. // Check if we passed the signal as a number:
  159. // The largest legal signal is 31, so let's parse on 5 bits
  160. sig, err = strconv.ParseUint(job.Args[1], 10, 5)
  161. if err != nil {
  162. // The signal is not a number, treat it as a string (either like "KILL" or like "SIGKILL")
  163. sig = uint64(signal.SignalMap[strings.TrimPrefix(job.Args[1], "SIG")])
  164. if sig == 0 {
  165. return job.Errorf("Invalid signal: %s", job.Args[1])
  166. }
  167. }
  168. }
  169. if container := srv.daemon.Get(name); container != nil {
  170. // If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
  171. if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
  172. if err := container.Kill(); err != nil {
  173. return job.Errorf("Cannot kill container %s: %s", name, err)
  174. }
  175. srv.LogEvent("kill", container.ID, srv.daemon.Repositories().ImageName(container.Image))
  176. } else {
  177. // Otherwise, just send the requested signal
  178. if err := container.KillSig(int(sig)); err != nil {
  179. return job.Errorf("Cannot kill container %s: %s", name, err)
  180. }
  181. // FIXME: Add event for signals
  182. }
  183. } else {
  184. return job.Errorf("No such container: %s", name)
  185. }
  186. return engine.StatusOK
  187. }
  188. func (srv *Server) Events(job *engine.Job) engine.Status {
  189. if len(job.Args) != 1 {
  190. return job.Errorf("Usage: %s FROM", job.Name)
  191. }
  192. var (
  193. from = job.Args[0]
  194. since = job.GetenvInt64("since")
  195. until = job.GetenvInt64("until")
  196. timeout = time.NewTimer(time.Unix(until, 0).Sub(time.Now()))
  197. )
  198. sendEvent := func(event *utils.JSONMessage) error {
  199. b, err := json.Marshal(event)
  200. if err != nil {
  201. return fmt.Errorf("JSON error")
  202. }
  203. _, err = job.Stdout.Write(b)
  204. if err != nil {
  205. // On error, evict the listener
  206. utils.Errorf("%s", err)
  207. srv.Lock()
  208. delete(srv.listeners, from)
  209. srv.Unlock()
  210. return err
  211. }
  212. return nil
  213. }
  214. listener := make(chan utils.JSONMessage)
  215. srv.Lock()
  216. if old, ok := srv.listeners[from]; ok {
  217. delete(srv.listeners, from)
  218. close(old)
  219. }
  220. srv.listeners[from] = listener
  221. srv.Unlock()
  222. job.Stdout.Write(nil) // flush
  223. if since != 0 {
  224. // If since, send previous events that happened after the timestamp and until timestamp
  225. for _, event := range srv.GetEvents() {
  226. if event.Time >= since && (event.Time <= until || until == 0) {
  227. err := sendEvent(&event)
  228. if err != nil && err.Error() == "JSON error" {
  229. continue
  230. }
  231. if err != nil {
  232. job.Error(err)
  233. return engine.StatusErr
  234. }
  235. }
  236. }
  237. }
  238. // If no until, disable timeout
  239. if until == 0 {
  240. timeout.Stop()
  241. }
  242. for {
  243. select {
  244. case event := <-listener:
  245. err := sendEvent(&event)
  246. if err != nil && err.Error() == "JSON error" {
  247. continue
  248. }
  249. if err != nil {
  250. return job.Error(err)
  251. }
  252. case <-timeout.C:
  253. return engine.StatusOK
  254. }
  255. }
  256. return engine.StatusOK
  257. }
  258. func (srv *Server) ContainerExport(job *engine.Job) engine.Status {
  259. if len(job.Args) != 1 {
  260. return job.Errorf("Usage: %s container_id", job.Name)
  261. }
  262. name := job.Args[0]
  263. if container := srv.daemon.Get(name); container != nil {
  264. data, err := container.Export()
  265. if err != nil {
  266. return job.Errorf("%s: %s", name, err)
  267. }
  268. defer data.Close()
  269. // Stream the entire contents of the container (basically a volatile snapshot)
  270. if _, err := io.Copy(job.Stdout, data); err != nil {
  271. return job.Errorf("%s: %s", name, err)
  272. }
  273. // FIXME: factor job-specific LogEvent to engine.Job.Run()
  274. srv.LogEvent("export", container.ID, srv.daemon.Repositories().ImageName(container.Image))
  275. return engine.StatusOK
  276. }
  277. return job.Errorf("No such container: %s", name)
  278. }
  279. // ImageExport exports all images with the given tag. All versions
  280. // containing the same tag are exported. The resulting output is an
  281. // uncompressed tar ball.
  282. // name is the set of tags to export.
  283. // out is the writer where the images are written to.
  284. func (srv *Server) ImageExport(job *engine.Job) engine.Status {
  285. if len(job.Args) != 1 {
  286. return job.Errorf("Usage: %s IMAGE\n", job.Name)
  287. }
  288. name := job.Args[0]
  289. // get image json
  290. tempdir, err := ioutil.TempDir("", "docker-export-")
  291. if err != nil {
  292. return job.Error(err)
  293. }
  294. defer os.RemoveAll(tempdir)
  295. utils.Debugf("Serializing %s", name)
  296. rootRepo, err := srv.daemon.Repositories().Get(name)
  297. if err != nil {
  298. return job.Error(err)
  299. }
  300. if rootRepo != nil {
  301. for _, id := range rootRepo {
  302. image, err := srv.ImageInspect(id)
  303. if err != nil {
  304. return job.Error(err)
  305. }
  306. if err := srv.exportImage(image, tempdir); err != nil {
  307. return job.Error(err)
  308. }
  309. }
  310. // write repositories
  311. rootRepoMap := map[string]graph.Repository{}
  312. rootRepoMap[name] = rootRepo
  313. rootRepoJson, _ := json.Marshal(rootRepoMap)
  314. if err := ioutil.WriteFile(path.Join(tempdir, "repositories"), rootRepoJson, os.FileMode(0644)); err != nil {
  315. return job.Error(err)
  316. }
  317. } else {
  318. image, err := srv.ImageInspect(name)
  319. if err != nil {
  320. return job.Error(err)
  321. }
  322. if err := srv.exportImage(image, tempdir); err != nil {
  323. return job.Error(err)
  324. }
  325. }
  326. fs, err := archive.Tar(tempdir, archive.Uncompressed)
  327. if err != nil {
  328. return job.Error(err)
  329. }
  330. defer fs.Close()
  331. if _, err := io.Copy(job.Stdout, fs); err != nil {
  332. return job.Error(err)
  333. }
  334. return engine.StatusOK
  335. }
  336. func (srv *Server) exportImage(img *image.Image, tempdir string) error {
  337. for i := img; i != nil; {
  338. // temporary directory
  339. tmpImageDir := path.Join(tempdir, i.ID)
  340. if err := os.Mkdir(tmpImageDir, os.FileMode(0755)); err != nil {
  341. if os.IsExist(err) {
  342. return nil
  343. }
  344. return err
  345. }
  346. var version = "1.0"
  347. var versionBuf = []byte(version)
  348. if err := ioutil.WriteFile(path.Join(tmpImageDir, "VERSION"), versionBuf, os.FileMode(0644)); err != nil {
  349. return err
  350. }
  351. // serialize json
  352. b, err := json.Marshal(i)
  353. if err != nil {
  354. return err
  355. }
  356. if err := ioutil.WriteFile(path.Join(tmpImageDir, "json"), b, os.FileMode(0644)); err != nil {
  357. return err
  358. }
  359. // serialize filesystem
  360. fs, err := i.TarLayer()
  361. if err != nil {
  362. return err
  363. }
  364. defer fs.Close()
  365. fsTar, err := os.Create(path.Join(tmpImageDir, "layer.tar"))
  366. if err != nil {
  367. return err
  368. }
  369. if written, err := io.Copy(fsTar, fs); err != nil {
  370. return err
  371. } else {
  372. utils.Debugf("rendered layer for %s of [%d] size", i.ID, written)
  373. }
  374. if err = fsTar.Close(); err != nil {
  375. return err
  376. }
  377. // find parent
  378. if i.Parent != "" {
  379. i, err = srv.ImageInspect(i.Parent)
  380. if err != nil {
  381. return err
  382. }
  383. } else {
  384. i = nil
  385. }
  386. }
  387. return nil
  388. }
  389. func (srv *Server) Build(job *engine.Job) engine.Status {
  390. if len(job.Args) != 0 {
  391. return job.Errorf("Usage: %s\n", job.Name)
  392. }
  393. var (
  394. remoteURL = job.Getenv("remote")
  395. repoName = job.Getenv("t")
  396. suppressOutput = job.GetenvBool("q")
  397. noCache = job.GetenvBool("nocache")
  398. rm = job.GetenvBool("rm")
  399. authConfig = &registry.AuthConfig{}
  400. configFile = &registry.ConfigFile{}
  401. tag string
  402. context io.ReadCloser
  403. )
  404. job.GetenvJson("authConfig", authConfig)
  405. job.GetenvJson("configFile", configFile)
  406. repoName, tag = utils.ParseRepositoryTag(repoName)
  407. if remoteURL == "" {
  408. context = ioutil.NopCloser(job.Stdin)
  409. } else if utils.IsGIT(remoteURL) {
  410. if !strings.HasPrefix(remoteURL, "git://") {
  411. remoteURL = "https://" + remoteURL
  412. }
  413. root, err := ioutil.TempDir("", "docker-build-git")
  414. if err != nil {
  415. return job.Error(err)
  416. }
  417. defer os.RemoveAll(root)
  418. if output, err := exec.Command("git", "clone", "--recursive", remoteURL, root).CombinedOutput(); err != nil {
  419. return job.Errorf("Error trying to use git: %s (%s)", err, output)
  420. }
  421. c, err := archive.Tar(root, archive.Uncompressed)
  422. if err != nil {
  423. return job.Error(err)
  424. }
  425. context = c
  426. } else if utils.IsURL(remoteURL) {
  427. f, err := utils.Download(remoteURL)
  428. if err != nil {
  429. return job.Error(err)
  430. }
  431. defer f.Body.Close()
  432. dockerFile, err := ioutil.ReadAll(f.Body)
  433. if err != nil {
  434. return job.Error(err)
  435. }
  436. c, err := archive.Generate("Dockerfile", string(dockerFile))
  437. if err != nil {
  438. return job.Error(err)
  439. }
  440. context = c
  441. }
  442. defer context.Close()
  443. sf := utils.NewStreamFormatter(job.GetenvBool("json"))
  444. b := NewBuildFile(srv,
  445. &utils.StdoutFormater{
  446. Writer: job.Stdout,
  447. StreamFormatter: sf,
  448. },
  449. &utils.StderrFormater{
  450. Writer: job.Stdout,
  451. StreamFormatter: sf,
  452. },
  453. !suppressOutput, !noCache, rm, job.Stdout, sf, authConfig, configFile)
  454. id, err := b.Build(context)
  455. if err != nil {
  456. return job.Error(err)
  457. }
  458. if repoName != "" {
  459. srv.daemon.Repositories().Set(repoName, tag, id, false)
  460. }
  461. return engine.StatusOK
  462. }
  463. // Loads a set of images into the repository. This is the complementary of ImageExport.
  464. // The input stream is an uncompressed tar ball containing images and metadata.
  465. func (srv *Server) ImageLoad(job *engine.Job) engine.Status {
  466. tmpImageDir, err := ioutil.TempDir("", "docker-import-")
  467. if err != nil {
  468. return job.Error(err)
  469. }
  470. defer os.RemoveAll(tmpImageDir)
  471. var (
  472. repoTarFile = path.Join(tmpImageDir, "repo.tar")
  473. repoDir = path.Join(tmpImageDir, "repo")
  474. )
  475. tarFile, err := os.Create(repoTarFile)
  476. if err != nil {
  477. return job.Error(err)
  478. }
  479. if _, err := io.Copy(tarFile, job.Stdin); err != nil {
  480. return job.Error(err)
  481. }
  482. tarFile.Close()
  483. repoFile, err := os.Open(repoTarFile)
  484. if err != nil {
  485. return job.Error(err)
  486. }
  487. if err := os.Mkdir(repoDir, os.ModeDir); err != nil {
  488. return job.Error(err)
  489. }
  490. if err := archive.Untar(repoFile, repoDir, nil); err != nil {
  491. return job.Error(err)
  492. }
  493. dirs, err := ioutil.ReadDir(repoDir)
  494. if err != nil {
  495. return job.Error(err)
  496. }
  497. for _, d := range dirs {
  498. if d.IsDir() {
  499. if err := srv.recursiveLoad(d.Name(), tmpImageDir); err != nil {
  500. return job.Error(err)
  501. }
  502. }
  503. }
  504. repositoriesJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", "repositories"))
  505. if err == nil {
  506. repositories := map[string]graph.Repository{}
  507. if err := json.Unmarshal(repositoriesJson, &repositories); err != nil {
  508. return job.Error(err)
  509. }
  510. for imageName, tagMap := range repositories {
  511. for tag, address := range tagMap {
  512. if err := srv.daemon.Repositories().Set(imageName, tag, address, true); err != nil {
  513. return job.Error(err)
  514. }
  515. }
  516. }
  517. } else if !os.IsNotExist(err) {
  518. return job.Error(err)
  519. }
  520. return engine.StatusOK
  521. }
  522. func (srv *Server) recursiveLoad(address, tmpImageDir string) error {
  523. if _, err := srv.ImageInspect(address); err != nil {
  524. utils.Debugf("Loading %s", address)
  525. imageJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", address, "json"))
  526. if err != nil {
  527. utils.Debugf("Error reading json", err)
  528. return err
  529. }
  530. layer, err := os.Open(path.Join(tmpImageDir, "repo", address, "layer.tar"))
  531. if err != nil {
  532. utils.Debugf("Error reading embedded tar", err)
  533. return err
  534. }
  535. img, err := image.NewImgJSON(imageJson)
  536. if err != nil {
  537. utils.Debugf("Error unmarshalling json", err)
  538. return err
  539. }
  540. if img.Parent != "" {
  541. if !srv.daemon.Graph().Exists(img.Parent) {
  542. if err := srv.recursiveLoad(img.Parent, tmpImageDir); err != nil {
  543. return err
  544. }
  545. }
  546. }
  547. if err := srv.daemon.Graph().Register(imageJson, layer, img); err != nil {
  548. return err
  549. }
  550. }
  551. utils.Debugf("Completed processing %s", address)
  552. return nil
  553. }
  554. // FIXME: 'insert' is deprecated and should be removed in a future version.
  555. func (srv *Server) ImageInsert(job *engine.Job) engine.Status {
  556. fmt.Fprintf(job.Stderr, "Warning: '%s' is deprecated and will be removed in a future version. Please use 'build' and 'ADD' instead.\n", job.Name)
  557. if len(job.Args) != 3 {
  558. return job.Errorf("Usage: %s IMAGE URL PATH\n", job.Name)
  559. }
  560. var (
  561. name = job.Args[0]
  562. url = job.Args[1]
  563. path = job.Args[2]
  564. )
  565. sf := utils.NewStreamFormatter(job.GetenvBool("json"))
  566. out := utils.NewWriteFlusher(job.Stdout)
  567. img, err := srv.daemon.Repositories().LookupImage(name)
  568. if err != nil {
  569. return job.Error(err)
  570. }
  571. file, err := utils.Download(url)
  572. if err != nil {
  573. return job.Error(err)
  574. }
  575. defer file.Body.Close()
  576. config, _, _, err := runconfig.Parse([]string{img.ID, "echo", "insert", url, path}, srv.daemon.SystemConfig())
  577. if err != nil {
  578. return job.Error(err)
  579. }
  580. c, _, err := srv.daemon.Create(config, "")
  581. if err != nil {
  582. return job.Error(err)
  583. }
  584. if err := c.Inject(utils.ProgressReader(file.Body, int(file.ContentLength), out, sf, false, utils.TruncateID(img.ID), "Downloading"), path); err != nil {
  585. return job.Error(err)
  586. }
  587. // FIXME: Handle custom repo, tag comment, author
  588. img, err = srv.daemon.Commit(c, "", "", img.Comment, img.Author, nil)
  589. if err != nil {
  590. out.Write(sf.FormatError(err))
  591. return engine.StatusErr
  592. }
  593. out.Write(sf.FormatStatus("", img.ID))
  594. return engine.StatusOK
  595. }
  596. func (srv *Server) ImagesViz(job *engine.Job) engine.Status {
  597. images, _ := srv.daemon.Graph().Map()
  598. if images == nil {
  599. return engine.StatusOK
  600. }
  601. job.Stdout.Write([]byte("digraph docker {\n"))
  602. var (
  603. parentImage *image.Image
  604. err error
  605. )
  606. for _, image := range images {
  607. parentImage, err = image.GetParent()
  608. if err != nil {
  609. return job.Errorf("Error while getting parent image: %v", err)
  610. }
  611. if parentImage != nil {
  612. job.Stdout.Write([]byte(" \"" + parentImage.ID + "\" -> \"" + image.ID + "\"\n"))
  613. } else {
  614. job.Stdout.Write([]byte(" base -> \"" + image.ID + "\" [style=invis]\n"))
  615. }
  616. }
  617. reporefs := make(map[string][]string)
  618. for name, repository := range srv.daemon.Repositories().Repositories {
  619. for tag, id := range repository {
  620. reporefs[utils.TruncateID(id)] = append(reporefs[utils.TruncateID(id)], fmt.Sprintf("%s:%s", name, tag))
  621. }
  622. }
  623. for id, repos := range reporefs {
  624. job.Stdout.Write([]byte(" \"" + id + "\" [label=\"" + id + "\\n" + strings.Join(repos, "\\n") + "\",shape=box,fillcolor=\"paleturquoise\",style=\"filled,rounded\"];\n"))
  625. }
  626. job.Stdout.Write([]byte(" base [style=invisible]\n}\n"))
  627. return engine.StatusOK
  628. }
  629. func (srv *Server) Images(job *engine.Job) engine.Status {
  630. var (
  631. allImages map[string]*image.Image
  632. err error
  633. )
  634. if job.GetenvBool("all") {
  635. allImages, err = srv.daemon.Graph().Map()
  636. } else {
  637. allImages, err = srv.daemon.Graph().Heads()
  638. }
  639. if err != nil {
  640. return job.Error(err)
  641. }
  642. lookup := make(map[string]*engine.Env)
  643. for name, repository := range srv.daemon.Repositories().Repositories {
  644. if job.Getenv("filter") != "" {
  645. if match, _ := path.Match(job.Getenv("filter"), name); !match {
  646. continue
  647. }
  648. }
  649. for tag, id := range repository {
  650. image, err := srv.daemon.Graph().Get(id)
  651. if err != nil {
  652. log.Printf("Warning: couldn't load %s from %s/%s: %s", id, name, tag, err)
  653. continue
  654. }
  655. if out, exists := lookup[id]; exists {
  656. out.SetList("RepoTags", append(out.GetList("RepoTags"), fmt.Sprintf("%s:%s", name, tag)))
  657. } else {
  658. out := &engine.Env{}
  659. delete(allImages, id)
  660. out.Set("ParentId", image.Parent)
  661. out.SetList("RepoTags", []string{fmt.Sprintf("%s:%s", name, tag)})
  662. out.Set("Id", image.ID)
  663. out.SetInt64("Created", image.Created.Unix())
  664. out.SetInt64("Size", image.Size)
  665. out.SetInt64("VirtualSize", image.GetParentsSize(0)+image.Size)
  666. lookup[id] = out
  667. }
  668. }
  669. }
  670. outs := engine.NewTable("Created", len(lookup))
  671. for _, value := range lookup {
  672. outs.Add(value)
  673. }
  674. // Display images which aren't part of a repository/tag
  675. if job.Getenv("filter") == "" {
  676. for _, image := range allImages {
  677. out := &engine.Env{}
  678. out.Set("ParentId", image.Parent)
  679. out.SetList("RepoTags", []string{"<none>:<none>"})
  680. out.Set("Id", image.ID)
  681. out.SetInt64("Created", image.Created.Unix())
  682. out.SetInt64("Size", image.Size)
  683. out.SetInt64("VirtualSize", image.GetParentsSize(0)+image.Size)
  684. outs.Add(out)
  685. }
  686. }
  687. outs.ReverseSort()
  688. if _, err := outs.WriteListTo(job.Stdout); err != nil {
  689. return job.Error(err)
  690. }
  691. return engine.StatusOK
  692. }
  693. func (srv *Server) DockerInfo(job *engine.Job) engine.Status {
  694. images, _ := srv.daemon.Graph().Map()
  695. var imgcount int
  696. if images == nil {
  697. imgcount = 0
  698. } else {
  699. imgcount = len(images)
  700. }
  701. kernelVersion := "<unknown>"
  702. if kv, err := utils.GetKernelVersion(); err == nil {
  703. kernelVersion = kv.String()
  704. }
  705. // 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)
  706. initPath := utils.DockerInitPath("")
  707. if initPath == "" {
  708. // if that fails, we'll just return the path from the daemon
  709. initPath = srv.daemon.SystemInitPath()
  710. }
  711. v := &engine.Env{}
  712. v.SetInt("Containers", len(srv.daemon.List()))
  713. v.SetInt("Images", imgcount)
  714. v.Set("Driver", srv.daemon.GraphDriver().String())
  715. v.SetJson("DriverStatus", srv.daemon.GraphDriver().Status())
  716. v.SetBool("MemoryLimit", srv.daemon.SystemConfig().MemoryLimit)
  717. v.SetBool("SwapLimit", srv.daemon.SystemConfig().SwapLimit)
  718. v.SetBool("IPv4Forwarding", !srv.daemon.SystemConfig().IPv4ForwardingDisabled)
  719. v.SetBool("Debug", os.Getenv("DEBUG") != "")
  720. v.SetInt("NFd", utils.GetTotalUsedFds())
  721. v.SetInt("NGoroutines", runtime.NumGoroutine())
  722. v.Set("ExecutionDriver", srv.daemon.ExecutionDriver().Name())
  723. v.SetInt("NEventsListener", len(srv.listeners))
  724. v.Set("KernelVersion", kernelVersion)
  725. v.Set("IndexServerAddress", registry.IndexServerAddress())
  726. v.Set("InitSha1", dockerversion.INITSHA1)
  727. v.Set("InitPath", initPath)
  728. if _, err := v.WriteTo(job.Stdout); err != nil {
  729. return job.Error(err)
  730. }
  731. return engine.StatusOK
  732. }
  733. func (srv *Server) DockerVersion(job *engine.Job) engine.Status {
  734. v := &engine.Env{}
  735. v.Set("Version", dockerversion.VERSION)
  736. v.SetJson("ApiVersion", api.APIVERSION)
  737. v.Set("GitCommit", dockerversion.GITCOMMIT)
  738. v.Set("GoVersion", runtime.Version())
  739. v.Set("Os", runtime.GOOS)
  740. v.Set("Arch", runtime.GOARCH)
  741. if kernelVersion, err := utils.GetKernelVersion(); err == nil {
  742. v.Set("KernelVersion", kernelVersion.String())
  743. }
  744. if _, err := v.WriteTo(job.Stdout); err != nil {
  745. return job.Error(err)
  746. }
  747. return engine.StatusOK
  748. }
  749. func (srv *Server) ImageHistory(job *engine.Job) engine.Status {
  750. if n := len(job.Args); n != 1 {
  751. return job.Errorf("Usage: %s IMAGE", job.Name)
  752. }
  753. name := job.Args[0]
  754. foundImage, err := srv.daemon.Repositories().LookupImage(name)
  755. if err != nil {
  756. return job.Error(err)
  757. }
  758. lookupMap := make(map[string][]string)
  759. for name, repository := range srv.daemon.Repositories().Repositories {
  760. for tag, id := range repository {
  761. // If the ID already has a reverse lookup, do not update it unless for "latest"
  762. if _, exists := lookupMap[id]; !exists {
  763. lookupMap[id] = []string{}
  764. }
  765. lookupMap[id] = append(lookupMap[id], name+":"+tag)
  766. }
  767. }
  768. outs := engine.NewTable("Created", 0)
  769. err = foundImage.WalkHistory(func(img *image.Image) error {
  770. out := &engine.Env{}
  771. out.Set("Id", img.ID)
  772. out.SetInt64("Created", img.Created.Unix())
  773. out.Set("CreatedBy", strings.Join(img.ContainerConfig.Cmd, " "))
  774. out.SetList("Tags", lookupMap[img.ID])
  775. out.SetInt64("Size", img.Size)
  776. outs.Add(out)
  777. return nil
  778. })
  779. outs.ReverseSort()
  780. if _, err := outs.WriteListTo(job.Stdout); err != nil {
  781. return job.Error(err)
  782. }
  783. return engine.StatusOK
  784. }
  785. func (srv *Server) ContainerTop(job *engine.Job) engine.Status {
  786. if len(job.Args) != 1 && len(job.Args) != 2 {
  787. return job.Errorf("Not enough arguments. Usage: %s CONTAINER [PS_ARGS]\n", job.Name)
  788. }
  789. var (
  790. name = job.Args[0]
  791. psArgs = "-ef"
  792. )
  793. if len(job.Args) == 2 && job.Args[1] != "" {
  794. psArgs = job.Args[1]
  795. }
  796. if container := srv.daemon.Get(name); container != nil {
  797. if !container.State.IsRunning() {
  798. return job.Errorf("Container %s is not running", name)
  799. }
  800. pids, err := srv.daemon.ExecutionDriver().GetPidsForContainer(container.ID)
  801. if err != nil {
  802. return job.Error(err)
  803. }
  804. output, err := exec.Command("ps", psArgs).Output()
  805. if err != nil {
  806. return job.Errorf("Error running ps: %s", err)
  807. }
  808. lines := strings.Split(string(output), "\n")
  809. header := strings.Fields(lines[0])
  810. out := &engine.Env{}
  811. out.SetList("Titles", header)
  812. pidIndex := -1
  813. for i, name := range header {
  814. if name == "PID" {
  815. pidIndex = i
  816. }
  817. }
  818. if pidIndex == -1 {
  819. return job.Errorf("Couldn't find PID field in ps output")
  820. }
  821. processes := [][]string{}
  822. for _, line := range lines[1:] {
  823. if len(line) == 0 {
  824. continue
  825. }
  826. fields := strings.Fields(line)
  827. p, err := strconv.Atoi(fields[pidIndex])
  828. if err != nil {
  829. return job.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err)
  830. }
  831. for _, pid := range pids {
  832. if pid == p {
  833. // Make sure number of fields equals number of header titles
  834. // merging "overhanging" fields
  835. process := fields[:len(header)-1]
  836. process = append(process, strings.Join(fields[len(header)-1:], " "))
  837. processes = append(processes, process)
  838. }
  839. }
  840. }
  841. out.SetJson("Processes", processes)
  842. out.WriteTo(job.Stdout)
  843. return engine.StatusOK
  844. }
  845. return job.Errorf("No such container: %s", name)
  846. }
  847. func (srv *Server) ContainerChanges(job *engine.Job) engine.Status {
  848. if n := len(job.Args); n != 1 {
  849. return job.Errorf("Usage: %s CONTAINER", job.Name)
  850. }
  851. name := job.Args[0]
  852. if container := srv.daemon.Get(name); container != nil {
  853. outs := engine.NewTable("", 0)
  854. changes, err := container.Changes()
  855. if err != nil {
  856. return job.Error(err)
  857. }
  858. for _, change := range changes {
  859. out := &engine.Env{}
  860. if err := out.Import(change); err != nil {
  861. return job.Error(err)
  862. }
  863. outs.Add(out)
  864. }
  865. if _, err := outs.WriteListTo(job.Stdout); err != nil {
  866. return job.Error(err)
  867. }
  868. } else {
  869. return job.Errorf("No such container: %s", name)
  870. }
  871. return engine.StatusOK
  872. }
  873. func (srv *Server) Containers(job *engine.Job) engine.Status {
  874. var (
  875. foundBefore bool
  876. displayed int
  877. all = job.GetenvBool("all")
  878. since = job.Getenv("since")
  879. before = job.Getenv("before")
  880. n = job.GetenvInt("limit")
  881. size = job.GetenvBool("size")
  882. )
  883. outs := engine.NewTable("Created", 0)
  884. names := map[string][]string{}
  885. srv.daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error {
  886. names[e.ID()] = append(names[e.ID()], p)
  887. return nil
  888. }, -1)
  889. var beforeCont, sinceCont *daemon.Container
  890. if before != "" {
  891. beforeCont = srv.daemon.Get(before)
  892. if beforeCont == nil {
  893. return job.Error(fmt.Errorf("Could not find container with name or id %s", before))
  894. }
  895. }
  896. if since != "" {
  897. sinceCont = srv.daemon.Get(since)
  898. if sinceCont == nil {
  899. return job.Error(fmt.Errorf("Could not find container with name or id %s", since))
  900. }
  901. }
  902. for _, container := range srv.daemon.List() {
  903. if !container.State.IsRunning() && !all && n <= 0 && since == "" && before == "" {
  904. continue
  905. }
  906. if before != "" && !foundBefore {
  907. if container.ID == beforeCont.ID {
  908. foundBefore = true
  909. }
  910. continue
  911. }
  912. if n > 0 && displayed == n {
  913. break
  914. }
  915. if since != "" {
  916. if container.ID == sinceCont.ID {
  917. break
  918. }
  919. }
  920. displayed++
  921. out := &engine.Env{}
  922. out.Set("Id", container.ID)
  923. out.SetList("Names", names[container.ID])
  924. out.Set("Image", srv.daemon.Repositories().ImageName(container.Image))
  925. if len(container.Args) > 0 {
  926. args := []string{}
  927. for _, arg := range container.Args {
  928. if strings.Contains(arg, " ") {
  929. args = append(args, fmt.Sprintf("'%s'", arg))
  930. } else {
  931. args = append(args, arg)
  932. }
  933. }
  934. argsAsString := strings.Join(args, " ")
  935. out.Set("Command", fmt.Sprintf("\"%s %s\"", container.Path, argsAsString))
  936. } else {
  937. out.Set("Command", fmt.Sprintf("\"%s\"", container.Path))
  938. }
  939. out.SetInt64("Created", container.Created.Unix())
  940. out.Set("Status", container.State.String())
  941. str, err := container.NetworkSettings.PortMappingAPI().ToListString()
  942. if err != nil {
  943. return job.Error(err)
  944. }
  945. out.Set("Ports", str)
  946. if size {
  947. sizeRw, sizeRootFs := container.GetSize()
  948. out.SetInt64("SizeRw", sizeRw)
  949. out.SetInt64("SizeRootFs", sizeRootFs)
  950. }
  951. outs.Add(out)
  952. }
  953. outs.ReverseSort()
  954. if _, err := outs.WriteListTo(job.Stdout); err != nil {
  955. return job.Error(err)
  956. }
  957. return engine.StatusOK
  958. }
  959. func (srv *Server) ContainerCommit(job *engine.Job) engine.Status {
  960. if len(job.Args) != 1 {
  961. return job.Errorf("Not enough arguments. Usage: %s CONTAINER\n", job.Name)
  962. }
  963. name := job.Args[0]
  964. container := srv.daemon.Get(name)
  965. if container == nil {
  966. return job.Errorf("No such container: %s", name)
  967. }
  968. var config = container.Config
  969. var newConfig runconfig.Config
  970. if err := job.GetenvJson("config", &newConfig); err != nil {
  971. return job.Error(err)
  972. }
  973. if err := runconfig.Merge(&newConfig, config); err != nil {
  974. return job.Error(err)
  975. }
  976. img, err := srv.daemon.Commit(container, job.Getenv("repo"), job.Getenv("tag"), job.Getenv("comment"), job.Getenv("author"), &newConfig)
  977. if err != nil {
  978. return job.Error(err)
  979. }
  980. job.Printf("%s\n", img.ID)
  981. return engine.StatusOK
  982. }
  983. func (srv *Server) ImageTag(job *engine.Job) engine.Status {
  984. if len(job.Args) != 2 && len(job.Args) != 3 {
  985. return job.Errorf("Usage: %s IMAGE REPOSITORY [TAG]\n", job.Name)
  986. }
  987. var tag string
  988. if len(job.Args) == 3 {
  989. tag = job.Args[2]
  990. }
  991. if err := srv.daemon.Repositories().Set(job.Args[1], tag, job.Args[0], job.GetenvBool("force")); err != nil {
  992. return job.Error(err)
  993. }
  994. return engine.StatusOK
  995. }
  996. func (srv *Server) pullImage(r *registry.Registry, out io.Writer, imgID, endpoint string, token []string, sf *utils.StreamFormatter) error {
  997. history, err := r.GetRemoteHistory(imgID, endpoint, token)
  998. if err != nil {
  999. return err
  1000. }
  1001. out.Write(sf.FormatProgress(utils.TruncateID(imgID), "Pulling dependent layers", nil))
  1002. // FIXME: Try to stream the images?
  1003. // FIXME: Launch the getRemoteImage() in goroutines
  1004. for i := len(history) - 1; i >= 0; i-- {
  1005. id := history[i]
  1006. // ensure no two downloads of the same layer happen at the same time
  1007. if c, err := srv.poolAdd("pull", "layer:"+id); err != nil {
  1008. utils.Errorf("Image (id: %s) pull is already running, skipping: %v", id, err)
  1009. <-c
  1010. }
  1011. defer srv.poolRemove("pull", "layer:"+id)
  1012. if !srv.daemon.Graph().Exists(id) {
  1013. out.Write(sf.FormatProgress(utils.TruncateID(id), "Pulling metadata", nil))
  1014. var (
  1015. imgJSON []byte
  1016. imgSize int
  1017. err error
  1018. img *image.Image
  1019. )
  1020. retries := 5
  1021. for j := 1; j <= retries; j++ {
  1022. imgJSON, imgSize, err = r.GetRemoteImageJSON(id, endpoint, token)
  1023. if err != nil && j == retries {
  1024. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
  1025. return err
  1026. } else if err != nil {
  1027. time.Sleep(time.Duration(j) * 500 * time.Millisecond)
  1028. continue
  1029. }
  1030. img, err = image.NewImgJSON(imgJSON)
  1031. if err != nil && j == retries {
  1032. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
  1033. return fmt.Errorf("Failed to parse json: %s", err)
  1034. } else if err != nil {
  1035. time.Sleep(time.Duration(j) * 500 * time.Millisecond)
  1036. continue
  1037. } else {
  1038. break
  1039. }
  1040. }
  1041. // Get the layer
  1042. out.Write(sf.FormatProgress(utils.TruncateID(id), "Pulling fs layer", nil))
  1043. layer, err := r.GetRemoteImageLayer(img.ID, endpoint, token)
  1044. if err != nil {
  1045. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
  1046. return err
  1047. }
  1048. defer layer.Close()
  1049. if err := srv.daemon.Graph().Register(imgJSON, utils.ProgressReader(layer, imgSize, out, sf, false, utils.TruncateID(id), "Downloading"), img); err != nil {
  1050. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error downloading dependent layers", nil))
  1051. return err
  1052. }
  1053. }
  1054. out.Write(sf.FormatProgress(utils.TruncateID(id), "Download complete", nil))
  1055. }
  1056. return nil
  1057. }
  1058. func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, localName, remoteName, askedTag string, sf *utils.StreamFormatter, parallel bool) error {
  1059. out.Write(sf.FormatStatus("", "Pulling repository %s", localName))
  1060. repoData, err := r.GetRepositoryData(remoteName)
  1061. if err != nil {
  1062. return err
  1063. }
  1064. utils.Debugf("Retrieving the tag list")
  1065. tagsList, err := r.GetRemoteTags(repoData.Endpoints, remoteName, repoData.Tokens)
  1066. if err != nil {
  1067. utils.Errorf("%v", err)
  1068. return err
  1069. }
  1070. for tag, id := range tagsList {
  1071. repoData.ImgList[id] = &registry.ImgData{
  1072. ID: id,
  1073. Tag: tag,
  1074. Checksum: "",
  1075. }
  1076. }
  1077. utils.Debugf("Registering tags")
  1078. // If no tag has been specified, pull them all
  1079. if askedTag == "" {
  1080. for tag, id := range tagsList {
  1081. repoData.ImgList[id].Tag = tag
  1082. }
  1083. } else {
  1084. // Otherwise, check that the tag exists and use only that one
  1085. id, exists := tagsList[askedTag]
  1086. if !exists {
  1087. return fmt.Errorf("Tag %s not found in repository %s", askedTag, localName)
  1088. }
  1089. repoData.ImgList[id].Tag = askedTag
  1090. }
  1091. errors := make(chan error)
  1092. for _, image := range repoData.ImgList {
  1093. downloadImage := func(img *registry.ImgData) {
  1094. if askedTag != "" && img.Tag != askedTag {
  1095. utils.Debugf("(%s) does not match %s (id: %s), skipping", img.Tag, askedTag, img.ID)
  1096. if parallel {
  1097. errors <- nil
  1098. }
  1099. return
  1100. }
  1101. if img.Tag == "" {
  1102. utils.Debugf("Image (id: %s) present in this repository but untagged, skipping", img.ID)
  1103. if parallel {
  1104. errors <- nil
  1105. }
  1106. return
  1107. }
  1108. // ensure no two downloads of the same image happen at the same time
  1109. if c, err := srv.poolAdd("pull", "img:"+img.ID); err != nil {
  1110. if c != nil {
  1111. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Layer already being pulled by another client. Waiting.", nil))
  1112. <-c
  1113. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Download complete", nil))
  1114. } else {
  1115. utils.Errorf("Image (id: %s) pull is already running, skipping: %v", img.ID, err)
  1116. }
  1117. if parallel {
  1118. errors <- nil
  1119. }
  1120. return
  1121. }
  1122. defer srv.poolRemove("pull", "img:"+img.ID)
  1123. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s", img.Tag, localName), nil))
  1124. success := false
  1125. var lastErr error
  1126. for _, ep := range repoData.Endpoints {
  1127. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s, endpoint: %s", img.Tag, localName, ep), nil))
  1128. if err := srv.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
  1129. // It's not ideal that only the last error is returned, it would be better to concatenate the errors.
  1130. // As the error is also given to the output stream the user will see the error.
  1131. lastErr = err
  1132. 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))
  1133. continue
  1134. }
  1135. success = true
  1136. break
  1137. }
  1138. if !success {
  1139. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Error pulling image (%s) from %s, %s", img.Tag, localName, lastErr), nil))
  1140. if parallel {
  1141. errors <- fmt.Errorf("Could not find repository on any of the indexed registries.")
  1142. return
  1143. }
  1144. }
  1145. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Download complete", nil))
  1146. if parallel {
  1147. errors <- nil
  1148. }
  1149. }
  1150. if parallel {
  1151. go downloadImage(image)
  1152. } else {
  1153. downloadImage(image)
  1154. }
  1155. }
  1156. if parallel {
  1157. var lastError error
  1158. for i := 0; i < len(repoData.ImgList); i++ {
  1159. if err := <-errors; err != nil {
  1160. lastError = err
  1161. }
  1162. }
  1163. if lastError != nil {
  1164. return lastError
  1165. }
  1166. }
  1167. for tag, id := range tagsList {
  1168. if askedTag != "" && tag != askedTag {
  1169. continue
  1170. }
  1171. if err := srv.daemon.Repositories().Set(localName, tag, id, true); err != nil {
  1172. return err
  1173. }
  1174. }
  1175. if err := srv.daemon.Repositories().Save(); err != nil {
  1176. return err
  1177. }
  1178. return nil
  1179. }
  1180. func (srv *Server) poolAdd(kind, key string) (chan struct{}, error) {
  1181. srv.Lock()
  1182. defer srv.Unlock()
  1183. if c, exists := srv.pullingPool[key]; exists {
  1184. return c, fmt.Errorf("pull %s is already in progress", key)
  1185. }
  1186. if c, exists := srv.pushingPool[key]; exists {
  1187. return c, fmt.Errorf("push %s is already in progress", key)
  1188. }
  1189. c := make(chan struct{})
  1190. switch kind {
  1191. case "pull":
  1192. srv.pullingPool[key] = c
  1193. case "push":
  1194. srv.pushingPool[key] = c
  1195. default:
  1196. return nil, fmt.Errorf("Unknown pool type")
  1197. }
  1198. return c, nil
  1199. }
  1200. func (srv *Server) poolRemove(kind, key string) error {
  1201. srv.Lock()
  1202. defer srv.Unlock()
  1203. switch kind {
  1204. case "pull":
  1205. if c, exists := srv.pullingPool[key]; exists {
  1206. close(c)
  1207. delete(srv.pullingPool, key)
  1208. }
  1209. case "push":
  1210. if c, exists := srv.pushingPool[key]; exists {
  1211. close(c)
  1212. delete(srv.pushingPool, key)
  1213. }
  1214. default:
  1215. return fmt.Errorf("Unknown pool type")
  1216. }
  1217. return nil
  1218. }
  1219. func (srv *Server) ImagePull(job *engine.Job) engine.Status {
  1220. if n := len(job.Args); n != 1 && n != 2 {
  1221. return job.Errorf("Usage: %s IMAGE [TAG]", job.Name)
  1222. }
  1223. var (
  1224. localName = job.Args[0]
  1225. tag string
  1226. sf = utils.NewStreamFormatter(job.GetenvBool("json"))
  1227. authConfig = &registry.AuthConfig{}
  1228. metaHeaders map[string][]string
  1229. )
  1230. if len(job.Args) > 1 {
  1231. tag = job.Args[1]
  1232. }
  1233. job.GetenvJson("authConfig", authConfig)
  1234. job.GetenvJson("metaHeaders", metaHeaders)
  1235. c, err := srv.poolAdd("pull", localName+":"+tag)
  1236. if err != nil {
  1237. if c != nil {
  1238. // Another pull of the same repository is already taking place; just wait for it to finish
  1239. job.Stdout.Write(sf.FormatStatus("", "Repository %s already being pulled by another client. Waiting.", localName))
  1240. <-c
  1241. return engine.StatusOK
  1242. }
  1243. return job.Error(err)
  1244. }
  1245. defer srv.poolRemove("pull", localName+":"+tag)
  1246. // Resolve the Repository name from fqn to endpoint + name
  1247. hostname, remoteName, err := registry.ResolveRepositoryName(localName)
  1248. if err != nil {
  1249. return job.Error(err)
  1250. }
  1251. endpoint, err := registry.ExpandAndVerifyRegistryUrl(hostname)
  1252. if err != nil {
  1253. return job.Error(err)
  1254. }
  1255. r, err := registry.NewRegistry(authConfig, registry.HTTPRequestFactory(metaHeaders), endpoint)
  1256. if err != nil {
  1257. return job.Error(err)
  1258. }
  1259. if endpoint == registry.IndexServerAddress() {
  1260. // If pull "index.docker.io/foo/bar", it's stored locally under "foo/bar"
  1261. localName = remoteName
  1262. }
  1263. if err = srv.pullRepository(r, job.Stdout, localName, remoteName, tag, sf, job.GetenvBool("parallel")); err != nil {
  1264. return job.Error(err)
  1265. }
  1266. return engine.StatusOK
  1267. }
  1268. // Retrieve the all the images to be uploaded in the correct order
  1269. func (srv *Server) getImageList(localRepo map[string]string, requestedTag string) ([]string, map[string][]string, error) {
  1270. var (
  1271. imageList []string
  1272. imagesSeen map[string]bool = make(map[string]bool)
  1273. tagsByImage map[string][]string = make(map[string][]string)
  1274. )
  1275. for tag, id := range localRepo {
  1276. if requestedTag != "" && requestedTag != tag {
  1277. continue
  1278. }
  1279. var imageListForThisTag []string
  1280. tagsByImage[id] = append(tagsByImage[id], tag)
  1281. for img, err := srv.daemon.Graph().Get(id); img != nil; img, err = img.GetParent() {
  1282. if err != nil {
  1283. return nil, nil, err
  1284. }
  1285. if imagesSeen[img.ID] {
  1286. // This image is already on the list, we can ignore it and all its parents
  1287. break
  1288. }
  1289. imagesSeen[img.ID] = true
  1290. imageListForThisTag = append(imageListForThisTag, img.ID)
  1291. }
  1292. // reverse the image list for this tag (so the "most"-parent image is first)
  1293. for i, j := 0, len(imageListForThisTag)-1; i < j; i, j = i+1, j-1 {
  1294. imageListForThisTag[i], imageListForThisTag[j] = imageListForThisTag[j], imageListForThisTag[i]
  1295. }
  1296. // append to main image list
  1297. imageList = append(imageList, imageListForThisTag...)
  1298. }
  1299. if len(imageList) == 0 {
  1300. return nil, nil, fmt.Errorf("No images found for the requested repository / tag")
  1301. }
  1302. utils.Debugf("Image list: %v", imageList)
  1303. utils.Debugf("Tags by image: %v", tagsByImage)
  1304. return imageList, tagsByImage, nil
  1305. }
  1306. func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, localName, remoteName string, localRepo map[string]string, tag string, sf *utils.StreamFormatter) error {
  1307. out = utils.NewWriteFlusher(out)
  1308. utils.Debugf("Local repo: %s", localRepo)
  1309. imgList, tagsByImage, err := srv.getImageList(localRepo, tag)
  1310. if err != nil {
  1311. return err
  1312. }
  1313. out.Write(sf.FormatStatus("", "Sending image list"))
  1314. var (
  1315. repoData *registry.RepositoryData
  1316. imageIndex []*registry.ImgData
  1317. )
  1318. for _, imgId := range imgList {
  1319. if tags, exists := tagsByImage[imgId]; exists {
  1320. // If an image has tags you must add an entry in the image index
  1321. // for each tag
  1322. for _, tag := range tags {
  1323. imageIndex = append(imageIndex, &registry.ImgData{
  1324. ID: imgId,
  1325. Tag: tag,
  1326. })
  1327. }
  1328. } else {
  1329. // If the image does not have a tag it still needs to be sent to the
  1330. // registry with an empty tag so that it is accociated with the repository
  1331. imageIndex = append(imageIndex, &registry.ImgData{
  1332. ID: imgId,
  1333. Tag: "",
  1334. })
  1335. }
  1336. }
  1337. utils.Debugf("Preparing to push %s with the following images and tags\n", localRepo)
  1338. for _, data := range imageIndex {
  1339. utils.Debugf("Pushing ID: %s with Tag: %s\n", data.ID, data.Tag)
  1340. }
  1341. // Register all the images in a repository with the registry
  1342. // If an image is not in this list it will not be associated with the repository
  1343. repoData, err = r.PushImageJSONIndex(remoteName, imageIndex, false, nil)
  1344. if err != nil {
  1345. return err
  1346. }
  1347. nTag := 1
  1348. if tag == "" {
  1349. nTag = len(localRepo)
  1350. }
  1351. for _, ep := range repoData.Endpoints {
  1352. out.Write(sf.FormatStatus("", "Pushing repository %s (%d tags)", localName, nTag))
  1353. for _, imgId := range imgList {
  1354. if r.LookupRemoteImage(imgId, ep, repoData.Tokens) {
  1355. out.Write(sf.FormatStatus("", "Image %s already pushed, skipping", utils.TruncateID(imgId)))
  1356. } else {
  1357. if _, err := srv.pushImage(r, out, remoteName, imgId, ep, repoData.Tokens, sf); err != nil {
  1358. // FIXME: Continue on error?
  1359. return err
  1360. }
  1361. }
  1362. for _, tag := range tagsByImage[imgId] {
  1363. out.Write(sf.FormatStatus("", "Pushing tag for rev [%s] on {%s}", utils.TruncateID(imgId), ep+"repositories/"+remoteName+"/tags/"+tag))
  1364. if err := r.PushRegistryTag(remoteName, imgId, tag, ep, repoData.Tokens); err != nil {
  1365. return err
  1366. }
  1367. }
  1368. }
  1369. }
  1370. if _, err := r.PushImageJSONIndex(remoteName, imageIndex, true, repoData.Endpoints); err != nil {
  1371. return err
  1372. }
  1373. return nil
  1374. }
  1375. func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgID, ep string, token []string, sf *utils.StreamFormatter) (checksum string, err error) {
  1376. out = utils.NewWriteFlusher(out)
  1377. jsonRaw, err := ioutil.ReadFile(path.Join(srv.daemon.Graph().Root, imgID, "json"))
  1378. if err != nil {
  1379. return "", fmt.Errorf("Cannot retrieve the path for {%s}: %s", imgID, err)
  1380. }
  1381. out.Write(sf.FormatProgress(utils.TruncateID(imgID), "Pushing", nil))
  1382. imgData := &registry.ImgData{
  1383. ID: imgID,
  1384. }
  1385. // Send the json
  1386. if err := r.PushImageJSONRegistry(imgData, jsonRaw, ep, token); err != nil {
  1387. if err == registry.ErrAlreadyExists {
  1388. out.Write(sf.FormatProgress(utils.TruncateID(imgData.ID), "Image already pushed, skipping", nil))
  1389. return "", nil
  1390. }
  1391. return "", err
  1392. }
  1393. layerData, err := srv.daemon.Graph().TempLayerArchive(imgID, archive.Uncompressed, sf, out)
  1394. if err != nil {
  1395. return "", fmt.Errorf("Failed to generate layer archive: %s", err)
  1396. }
  1397. defer os.RemoveAll(layerData.Name())
  1398. // Send the layer
  1399. utils.Debugf("rendered layer for %s of [%d] size", imgData.ID, layerData.Size)
  1400. checksum, checksumPayload, err := r.PushImageLayerRegistry(imgData.ID, utils.ProgressReader(layerData, int(layerData.Size), out, sf, false, utils.TruncateID(imgData.ID), "Pushing"), ep, token, jsonRaw)
  1401. if err != nil {
  1402. return "", err
  1403. }
  1404. imgData.Checksum = checksum
  1405. imgData.ChecksumPayload = checksumPayload
  1406. // Send the checksum
  1407. if err := r.PushImageChecksumRegistry(imgData, ep, token); err != nil {
  1408. return "", err
  1409. }
  1410. out.Write(sf.FormatProgress(utils.TruncateID(imgData.ID), "Image successfully pushed", nil))
  1411. return imgData.Checksum, nil
  1412. }
  1413. // FIXME: Allow to interrupt current push when new push of same image is done.
  1414. func (srv *Server) ImagePush(job *engine.Job) engine.Status {
  1415. if n := len(job.Args); n != 1 {
  1416. return job.Errorf("Usage: %s IMAGE", job.Name)
  1417. }
  1418. var (
  1419. localName = job.Args[0]
  1420. sf = utils.NewStreamFormatter(job.GetenvBool("json"))
  1421. authConfig = &registry.AuthConfig{}
  1422. metaHeaders map[string][]string
  1423. )
  1424. tag := job.Getenv("tag")
  1425. job.GetenvJson("authConfig", authConfig)
  1426. job.GetenvJson("metaHeaders", metaHeaders)
  1427. if _, err := srv.poolAdd("push", localName); err != nil {
  1428. return job.Error(err)
  1429. }
  1430. defer srv.poolRemove("push", localName)
  1431. // Resolve the Repository name from fqn to endpoint + name
  1432. hostname, remoteName, err := registry.ResolveRepositoryName(localName)
  1433. if err != nil {
  1434. return job.Error(err)
  1435. }
  1436. endpoint, err := registry.ExpandAndVerifyRegistryUrl(hostname)
  1437. if err != nil {
  1438. return job.Error(err)
  1439. }
  1440. img, err := srv.daemon.Graph().Get(localName)
  1441. r, err2 := registry.NewRegistry(authConfig, registry.HTTPRequestFactory(metaHeaders), endpoint)
  1442. if err2 != nil {
  1443. return job.Error(err2)
  1444. }
  1445. if err != nil {
  1446. reposLen := 1
  1447. if tag == "" {
  1448. reposLen = len(srv.daemon.Repositories().Repositories[localName])
  1449. }
  1450. job.Stdout.Write(sf.FormatStatus("", "The push refers to a repository [%s] (len: %d)", localName, reposLen))
  1451. // If it fails, try to get the repository
  1452. if localRepo, exists := srv.daemon.Repositories().Repositories[localName]; exists {
  1453. if err := srv.pushRepository(r, job.Stdout, localName, remoteName, localRepo, tag, sf); err != nil {
  1454. return job.Error(err)
  1455. }
  1456. return engine.StatusOK
  1457. }
  1458. return job.Error(err)
  1459. }
  1460. var token []string
  1461. job.Stdout.Write(sf.FormatStatus("", "The push refers to an image: [%s]", localName))
  1462. if _, err := srv.pushImage(r, job.Stdout, remoteName, img.ID, endpoint, token, sf); err != nil {
  1463. return job.Error(err)
  1464. }
  1465. return engine.StatusOK
  1466. }
  1467. func (srv *Server) ImageImport(job *engine.Job) engine.Status {
  1468. if n := len(job.Args); n != 2 && n != 3 {
  1469. return job.Errorf("Usage: %s SRC REPO [TAG]", job.Name)
  1470. }
  1471. var (
  1472. src = job.Args[0]
  1473. repo = job.Args[1]
  1474. tag string
  1475. sf = utils.NewStreamFormatter(job.GetenvBool("json"))
  1476. archive archive.ArchiveReader
  1477. resp *http.Response
  1478. )
  1479. if len(job.Args) > 2 {
  1480. tag = job.Args[2]
  1481. }
  1482. if src == "-" {
  1483. archive = job.Stdin
  1484. } else {
  1485. u, err := url.Parse(src)
  1486. if err != nil {
  1487. return job.Error(err)
  1488. }
  1489. if u.Scheme == "" {
  1490. u.Scheme = "http"
  1491. u.Host = src
  1492. u.Path = ""
  1493. }
  1494. job.Stdout.Write(sf.FormatStatus("", "Downloading from %s", u))
  1495. // Download with curl (pretty progress bar)
  1496. // If curl is not available, fallback to http.Get()
  1497. resp, err = utils.Download(u.String())
  1498. if err != nil {
  1499. return job.Error(err)
  1500. }
  1501. progressReader := utils.ProgressReader(resp.Body, int(resp.ContentLength), job.Stdout, sf, true, "", "Importing")
  1502. defer progressReader.Close()
  1503. archive = progressReader
  1504. }
  1505. img, err := srv.daemon.Graph().Create(archive, "", "", "Imported from "+src, "", nil, nil)
  1506. if err != nil {
  1507. return job.Error(err)
  1508. }
  1509. // Optionally register the image at REPO/TAG
  1510. if repo != "" {
  1511. if err := srv.daemon.Repositories().Set(repo, tag, img.ID, true); err != nil {
  1512. return job.Error(err)
  1513. }
  1514. }
  1515. job.Stdout.Write(sf.FormatStatus("", img.ID))
  1516. return engine.StatusOK
  1517. }
  1518. func (srv *Server) ContainerCreate(job *engine.Job) engine.Status {
  1519. var name string
  1520. if len(job.Args) == 1 {
  1521. name = job.Args[0]
  1522. } else if len(job.Args) > 1 {
  1523. return job.Errorf("Usage: %s", job.Name)
  1524. }
  1525. config := runconfig.ContainerConfigFromJob(job)
  1526. if config.Memory != 0 && config.Memory < 524288 {
  1527. return job.Errorf("Minimum memory limit allowed is 512k")
  1528. }
  1529. if config.Memory > 0 && !srv.daemon.SystemConfig().MemoryLimit {
  1530. job.Errorf("Your kernel does not support memory limit capabilities. Limitation discarded.\n")
  1531. config.Memory = 0
  1532. }
  1533. if config.Memory > 0 && !srv.daemon.SystemConfig().SwapLimit {
  1534. job.Errorf("Your kernel does not support swap limit capabilities. Limitation discarded.\n")
  1535. config.MemorySwap = -1
  1536. }
  1537. container, buildWarnings, err := srv.daemon.Create(config, name)
  1538. if err != nil {
  1539. if srv.daemon.Graph().IsNotExist(err) {
  1540. _, tag := utils.ParseRepositoryTag(config.Image)
  1541. if tag == "" {
  1542. tag = graph.DEFAULTTAG
  1543. }
  1544. return job.Errorf("No such image: %s (tag: %s)", config.Image, tag)
  1545. }
  1546. return job.Error(err)
  1547. }
  1548. if !container.Config.NetworkDisabled && srv.daemon.SystemConfig().IPv4ForwardingDisabled {
  1549. job.Errorf("IPv4 forwarding is disabled.\n")
  1550. }
  1551. srv.LogEvent("create", container.ID, srv.daemon.Repositories().ImageName(container.Image))
  1552. // FIXME: this is necessary because daemon.Create might return a nil container
  1553. // with a non-nil error. This should not happen! Once it's fixed we
  1554. // can remove this workaround.
  1555. if container != nil {
  1556. job.Printf("%s\n", container.ID)
  1557. }
  1558. for _, warning := range buildWarnings {
  1559. job.Errorf("%s\n", warning)
  1560. }
  1561. return engine.StatusOK
  1562. }
  1563. func (srv *Server) ContainerRestart(job *engine.Job) engine.Status {
  1564. if len(job.Args) != 1 {
  1565. return job.Errorf("Usage: %s CONTAINER\n", job.Name)
  1566. }
  1567. var (
  1568. name = job.Args[0]
  1569. t = 10
  1570. )
  1571. if job.EnvExists("t") {
  1572. t = job.GetenvInt("t")
  1573. }
  1574. if container := srv.daemon.Get(name); container != nil {
  1575. if err := container.Restart(int(t)); err != nil {
  1576. return job.Errorf("Cannot restart container %s: %s\n", name, err)
  1577. }
  1578. srv.LogEvent("restart", container.ID, srv.daemon.Repositories().ImageName(container.Image))
  1579. } else {
  1580. return job.Errorf("No such container: %s\n", name)
  1581. }
  1582. return engine.StatusOK
  1583. }
  1584. func (srv *Server) ContainerDestroy(job *engine.Job) engine.Status {
  1585. if len(job.Args) != 1 {
  1586. return job.Errorf("Not enough arguments. Usage: %s CONTAINER\n", job.Name)
  1587. }
  1588. name := job.Args[0]
  1589. removeVolume := job.GetenvBool("removeVolume")
  1590. removeLink := job.GetenvBool("removeLink")
  1591. forceRemove := job.GetenvBool("forceRemove")
  1592. container := srv.daemon.Get(name)
  1593. if removeLink {
  1594. if container == nil {
  1595. return job.Errorf("No such link: %s", name)
  1596. }
  1597. name, err := daemon.GetFullContainerName(name)
  1598. if err != nil {
  1599. job.Error(err)
  1600. }
  1601. parent, n := path.Split(name)
  1602. if parent == "/" {
  1603. return job.Errorf("Conflict, cannot remove the default name of the container")
  1604. }
  1605. pe := srv.daemon.ContainerGraph().Get(parent)
  1606. if pe == nil {
  1607. return job.Errorf("Cannot get parent %s for name %s", parent, name)
  1608. }
  1609. parentContainer := srv.daemon.Get(pe.ID())
  1610. if parentContainer != nil {
  1611. parentContainer.DisableLink(n)
  1612. }
  1613. if err := srv.daemon.ContainerGraph().Delete(name); err != nil {
  1614. return job.Error(err)
  1615. }
  1616. return engine.StatusOK
  1617. }
  1618. if container != nil {
  1619. if container.State.IsRunning() {
  1620. if forceRemove {
  1621. if err := container.Stop(5); err != nil {
  1622. return job.Errorf("Could not stop running container, cannot remove - %v", err)
  1623. }
  1624. } else {
  1625. return job.Errorf("Impossible to remove a running container, please stop it first or use -f")
  1626. }
  1627. }
  1628. if err := srv.daemon.Destroy(container); err != nil {
  1629. return job.Errorf("Cannot destroy container %s: %s", name, err)
  1630. }
  1631. srv.LogEvent("destroy", container.ID, srv.daemon.Repositories().ImageName(container.Image))
  1632. if removeVolume {
  1633. var (
  1634. volumes = make(map[string]struct{})
  1635. binds = make(map[string]struct{})
  1636. usedVolumes = make(map[string]*daemon.Container)
  1637. )
  1638. // the volume id is always the base of the path
  1639. getVolumeId := func(p string) string {
  1640. return filepath.Base(strings.TrimSuffix(p, "/layer"))
  1641. }
  1642. // populate bind map so that they can be skipped and not removed
  1643. for _, bind := range container.HostConfig().Binds {
  1644. source := strings.Split(bind, ":")[0]
  1645. // TODO: refactor all volume stuff, all of it
  1646. // it is very important that we eval the link or comparing the keys to container.Volumes will not work
  1647. //
  1648. // eval symlink can fail, ref #5244 if we receive an is not exist error we can ignore it
  1649. p, err := filepath.EvalSymlinks(source)
  1650. if err != nil && !os.IsNotExist(err) {
  1651. return job.Error(err)
  1652. }
  1653. if p != "" {
  1654. source = p
  1655. }
  1656. binds[source] = struct{}{}
  1657. }
  1658. // Store all the deleted containers volumes
  1659. for _, volumeId := range container.Volumes {
  1660. // Skip the volumes mounted from external
  1661. // bind mounts here will will be evaluated for a symlink
  1662. if _, exists := binds[volumeId]; exists {
  1663. continue
  1664. }
  1665. volumeId = getVolumeId(volumeId)
  1666. volumes[volumeId] = struct{}{}
  1667. }
  1668. // Retrieve all volumes from all remaining containers
  1669. for _, container := range srv.daemon.List() {
  1670. for _, containerVolumeId := range container.Volumes {
  1671. containerVolumeId = getVolumeId(containerVolumeId)
  1672. usedVolumes[containerVolumeId] = container
  1673. }
  1674. }
  1675. for volumeId := range volumes {
  1676. // If the requested volu
  1677. if c, exists := usedVolumes[volumeId]; exists {
  1678. log.Printf("The volume %s is used by the container %s. Impossible to remove it. Skipping.\n", volumeId, c.ID)
  1679. continue
  1680. }
  1681. if err := srv.daemon.Volumes().Delete(volumeId); err != nil {
  1682. return job.Errorf("Error calling volumes.Delete(%q): %v", volumeId, err)
  1683. }
  1684. }
  1685. }
  1686. } else {
  1687. return job.Errorf("No such container: %s", name)
  1688. }
  1689. return engine.StatusOK
  1690. }
  1691. func (srv *Server) DeleteImage(name string, imgs *engine.Table, first, force, noprune bool) error {
  1692. var (
  1693. repoName, tag string
  1694. tags = []string{}
  1695. tagDeleted bool
  1696. )
  1697. repoName, tag = utils.ParseRepositoryTag(name)
  1698. if tag == "" {
  1699. tag = graph.DEFAULTTAG
  1700. }
  1701. img, err := srv.daemon.Repositories().LookupImage(name)
  1702. if err != nil {
  1703. if r, _ := srv.daemon.Repositories().Get(repoName); r != nil {
  1704. return fmt.Errorf("No such image: %s:%s", repoName, tag)
  1705. }
  1706. return fmt.Errorf("No such image: %s", name)
  1707. }
  1708. if strings.Contains(img.ID, name) {
  1709. repoName = ""
  1710. tag = ""
  1711. }
  1712. byParents, err := srv.daemon.Graph().ByParent()
  1713. if err != nil {
  1714. return err
  1715. }
  1716. //If delete by id, see if the id belong only to one repository
  1717. if repoName == "" {
  1718. for _, repoAndTag := range srv.daemon.Repositories().ByID()[img.ID] {
  1719. parsedRepo, parsedTag := utils.ParseRepositoryTag(repoAndTag)
  1720. if repoName == "" || repoName == parsedRepo {
  1721. repoName = parsedRepo
  1722. if parsedTag != "" {
  1723. tags = append(tags, parsedTag)
  1724. }
  1725. } else if repoName != parsedRepo && !force {
  1726. // the id belongs to multiple repos, like base:latest and user:test,
  1727. // in that case return conflict
  1728. return fmt.Errorf("Conflict, cannot delete image %s because it is tagged in multiple repositories, use -f to force", name)
  1729. }
  1730. }
  1731. } else {
  1732. tags = append(tags, tag)
  1733. }
  1734. if !first && len(tags) > 0 {
  1735. return nil
  1736. }
  1737. //Untag the current image
  1738. for _, tag := range tags {
  1739. tagDeleted, err = srv.daemon.Repositories().Delete(repoName, tag)
  1740. if err != nil {
  1741. return err
  1742. }
  1743. if tagDeleted {
  1744. out := &engine.Env{}
  1745. out.Set("Untagged", repoName+":"+tag)
  1746. imgs.Add(out)
  1747. srv.LogEvent("untag", img.ID, "")
  1748. }
  1749. }
  1750. tags = srv.daemon.Repositories().ByID()[img.ID]
  1751. if (len(tags) <= 1 && repoName == "") || len(tags) == 0 {
  1752. if len(byParents[img.ID]) == 0 {
  1753. if err := srv.canDeleteImage(img.ID, force, tagDeleted); err != nil {
  1754. return err
  1755. }
  1756. if err := srv.daemon.Repositories().DeleteAll(img.ID); err != nil {
  1757. return err
  1758. }
  1759. if err := srv.daemon.Graph().Delete(img.ID); err != nil {
  1760. return err
  1761. }
  1762. out := &engine.Env{}
  1763. out.Set("Deleted", img.ID)
  1764. imgs.Add(out)
  1765. srv.LogEvent("delete", img.ID, "")
  1766. if img.Parent != "" && !noprune {
  1767. err := srv.DeleteImage(img.Parent, imgs, false, force, noprune)
  1768. if first {
  1769. return err
  1770. }
  1771. }
  1772. }
  1773. }
  1774. return nil
  1775. }
  1776. func (srv *Server) ImageDelete(job *engine.Job) engine.Status {
  1777. if n := len(job.Args); n != 1 {
  1778. return job.Errorf("Usage: %s IMAGE", job.Name)
  1779. }
  1780. imgs := engine.NewTable("", 0)
  1781. if err := srv.DeleteImage(job.Args[0], imgs, true, job.GetenvBool("force"), job.GetenvBool("noprune")); err != nil {
  1782. return job.Error(err)
  1783. }
  1784. if len(imgs.Data) == 0 {
  1785. return job.Errorf("Conflict, %s wasn't deleted", job.Args[0])
  1786. }
  1787. if _, err := imgs.WriteListTo(job.Stdout); err != nil {
  1788. return job.Error(err)
  1789. }
  1790. return engine.StatusOK
  1791. }
  1792. func (srv *Server) canDeleteImage(imgID string, force, untagged bool) error {
  1793. var message string
  1794. if untagged {
  1795. message = " (docker untagged the image)"
  1796. }
  1797. for _, container := range srv.daemon.List() {
  1798. parent, err := srv.daemon.Repositories().LookupImage(container.Image)
  1799. if err != nil {
  1800. return err
  1801. }
  1802. if err := parent.WalkHistory(func(p *image.Image) error {
  1803. if imgID == p.ID {
  1804. if container.State.IsRunning() {
  1805. if force {
  1806. return fmt.Errorf("Conflict, cannot force delete %s because the running container %s is using it%s, stop it and retry", utils.TruncateID(imgID), utils.TruncateID(container.ID), message)
  1807. }
  1808. return fmt.Errorf("Conflict, cannot delete %s because the running container %s is using it%s, stop it and use -f to force", utils.TruncateID(imgID), utils.TruncateID(container.ID), message)
  1809. } else if !force {
  1810. return fmt.Errorf("Conflict, cannot delete %s because the container %s is using it%s, use -f to force", utils.TruncateID(imgID), utils.TruncateID(container.ID), message)
  1811. }
  1812. }
  1813. return nil
  1814. }); err != nil {
  1815. return err
  1816. }
  1817. }
  1818. return nil
  1819. }
  1820. func (srv *Server) ImageGetCached(imgID string, config *runconfig.Config) (*image.Image, error) {
  1821. // Retrieve all images
  1822. images, err := srv.daemon.Graph().Map()
  1823. if err != nil {
  1824. return nil, err
  1825. }
  1826. // Store the tree in a map of map (map[parentId][childId])
  1827. imageMap := make(map[string]map[string]struct{})
  1828. for _, img := range images {
  1829. if _, exists := imageMap[img.Parent]; !exists {
  1830. imageMap[img.Parent] = make(map[string]struct{})
  1831. }
  1832. imageMap[img.Parent][img.ID] = struct{}{}
  1833. }
  1834. // Loop on the children of the given image and check the config
  1835. var match *image.Image
  1836. for elem := range imageMap[imgID] {
  1837. img, err := srv.daemon.Graph().Get(elem)
  1838. if err != nil {
  1839. return nil, err
  1840. }
  1841. if runconfig.Compare(&img.ContainerConfig, config) {
  1842. if match == nil || match.Created.Before(img.Created) {
  1843. match = img
  1844. }
  1845. }
  1846. }
  1847. return match, nil
  1848. }
  1849. func (srv *Server) RegisterLinks(container *daemon.Container, hostConfig *runconfig.HostConfig) error {
  1850. daemon := srv.daemon
  1851. if hostConfig != nil && hostConfig.Links != nil {
  1852. for _, l := range hostConfig.Links {
  1853. parts, err := utils.PartParser("name:alias", l)
  1854. if err != nil {
  1855. return err
  1856. }
  1857. child, err := srv.daemon.GetByName(parts["name"])
  1858. if err != nil {
  1859. return err
  1860. }
  1861. if child == nil {
  1862. return fmt.Errorf("Could not get container for %s", parts["name"])
  1863. }
  1864. if err := daemon.RegisterLink(container, child, parts["alias"]); err != nil {
  1865. return err
  1866. }
  1867. }
  1868. // After we load all the links into the daemon
  1869. // set them to nil on the hostconfig
  1870. hostConfig.Links = nil
  1871. if err := container.WriteHostConfig(); err != nil {
  1872. return err
  1873. }
  1874. }
  1875. return nil
  1876. }
  1877. func (srv *Server) ContainerStart(job *engine.Job) engine.Status {
  1878. if len(job.Args) < 1 {
  1879. return job.Errorf("Usage: %s container_id", job.Name)
  1880. }
  1881. var (
  1882. name = job.Args[0]
  1883. daemon = srv.daemon
  1884. container = daemon.Get(name)
  1885. )
  1886. if container == nil {
  1887. return job.Errorf("No such container: %s", name)
  1888. }
  1889. // If no environment was set, then no hostconfig was passed.
  1890. if len(job.Environ()) > 0 {
  1891. hostConfig := runconfig.ContainerHostConfigFromJob(job)
  1892. // Validate the HostConfig binds. Make sure that:
  1893. // 1) the source of a bind mount isn't /
  1894. // The bind mount "/:/foo" isn't allowed.
  1895. // 2) Check that the source exists
  1896. // The source to be bind mounted must exist.
  1897. for _, bind := range hostConfig.Binds {
  1898. splitBind := strings.Split(bind, ":")
  1899. source := splitBind[0]
  1900. // refuse to bind mount "/" to the container
  1901. if source == "/" {
  1902. return job.Errorf("Invalid bind mount '%s' : source can't be '/'", bind)
  1903. }
  1904. // ensure the source exists on the host
  1905. _, err := os.Stat(source)
  1906. if err != nil && os.IsNotExist(err) {
  1907. err = os.MkdirAll(source, 0755)
  1908. if err != nil {
  1909. return job.Errorf("Could not create local directory '%s' for bind mount: %s!", source, err.Error())
  1910. }
  1911. }
  1912. }
  1913. // Register any links from the host config before starting the container
  1914. if err := srv.RegisterLinks(container, hostConfig); err != nil {
  1915. return job.Error(err)
  1916. }
  1917. container.SetHostConfig(hostConfig)
  1918. container.ToDisk()
  1919. }
  1920. if err := container.Start(); err != nil {
  1921. return job.Errorf("Cannot start container %s: %s", name, err)
  1922. }
  1923. srv.LogEvent("start", container.ID, daemon.Repositories().ImageName(container.Image))
  1924. return engine.StatusOK
  1925. }
  1926. func (srv *Server) ContainerStop(job *engine.Job) engine.Status {
  1927. if len(job.Args) != 1 {
  1928. return job.Errorf("Usage: %s CONTAINER\n", job.Name)
  1929. }
  1930. var (
  1931. name = job.Args[0]
  1932. t = 10
  1933. )
  1934. if job.EnvExists("t") {
  1935. t = job.GetenvInt("t")
  1936. }
  1937. if container := srv.daemon.Get(name); container != nil {
  1938. if err := container.Stop(int(t)); err != nil {
  1939. return job.Errorf("Cannot stop container %s: %s\n", name, err)
  1940. }
  1941. srv.LogEvent("stop", container.ID, srv.daemon.Repositories().ImageName(container.Image))
  1942. } else {
  1943. return job.Errorf("No such container: %s\n", name)
  1944. }
  1945. return engine.StatusOK
  1946. }
  1947. func (srv *Server) ContainerWait(job *engine.Job) engine.Status {
  1948. if len(job.Args) != 1 {
  1949. return job.Errorf("Usage: %s", job.Name)
  1950. }
  1951. name := job.Args[0]
  1952. if container := srv.daemon.Get(name); container != nil {
  1953. status := container.Wait()
  1954. job.Printf("%d\n", status)
  1955. return engine.StatusOK
  1956. }
  1957. return job.Errorf("%s: no such container: %s", job.Name, name)
  1958. }
  1959. func (srv *Server) ContainerResize(job *engine.Job) engine.Status {
  1960. if len(job.Args) != 3 {
  1961. return job.Errorf("Not enough arguments. Usage: %s CONTAINER HEIGHT WIDTH\n", job.Name)
  1962. }
  1963. name := job.Args[0]
  1964. height, err := strconv.Atoi(job.Args[1])
  1965. if err != nil {
  1966. return job.Error(err)
  1967. }
  1968. width, err := strconv.Atoi(job.Args[2])
  1969. if err != nil {
  1970. return job.Error(err)
  1971. }
  1972. if container := srv.daemon.Get(name); container != nil {
  1973. if err := container.Resize(height, width); err != nil {
  1974. return job.Error(err)
  1975. }
  1976. return engine.StatusOK
  1977. }
  1978. return job.Errorf("No such container: %s", name)
  1979. }
  1980. func (srv *Server) ContainerLogs(job *engine.Job) engine.Status {
  1981. if len(job.Args) != 1 {
  1982. return job.Errorf("Usage: %s CONTAINER\n", job.Name)
  1983. }
  1984. var (
  1985. name = job.Args[0]
  1986. stdout = job.GetenvBool("stdout")
  1987. stderr = job.GetenvBool("stderr")
  1988. follow = job.GetenvBool("follow")
  1989. times = job.GetenvBool("timestamps")
  1990. format string
  1991. )
  1992. if !(stdout || stderr) {
  1993. return job.Errorf("You must choose at least one stream")
  1994. }
  1995. if times {
  1996. format = time.StampMilli
  1997. }
  1998. container := srv.daemon.Get(name)
  1999. if container == nil {
  2000. return job.Errorf("No such container: %s", name)
  2001. }
  2002. cLog, err := container.ReadLog("json")
  2003. if err != nil && os.IsNotExist(err) {
  2004. // Legacy logs
  2005. utils.Debugf("Old logs format")
  2006. if stdout {
  2007. cLog, err := container.ReadLog("stdout")
  2008. if err != nil {
  2009. utils.Errorf("Error reading logs (stdout): %s", err)
  2010. } else if _, err := io.Copy(job.Stdout, cLog); err != nil {
  2011. utils.Errorf("Error streaming logs (stdout): %s", err)
  2012. }
  2013. }
  2014. if stderr {
  2015. cLog, err := container.ReadLog("stderr")
  2016. if err != nil {
  2017. utils.Errorf("Error reading logs (stderr): %s", err)
  2018. } else if _, err := io.Copy(job.Stderr, cLog); err != nil {
  2019. utils.Errorf("Error streaming logs (stderr): %s", err)
  2020. }
  2021. }
  2022. } else if err != nil {
  2023. utils.Errorf("Error reading logs (json): %s", err)
  2024. } else {
  2025. dec := json.NewDecoder(cLog)
  2026. for {
  2027. l := &utils.JSONLog{}
  2028. if err := dec.Decode(l); err == io.EOF {
  2029. break
  2030. } else if err != nil {
  2031. utils.Errorf("Error streaming logs: %s", err)
  2032. break
  2033. }
  2034. logLine := l.Log
  2035. if times {
  2036. logLine = fmt.Sprintf("[%s] %s", l.Created.Format(format), logLine)
  2037. }
  2038. if l.Stream == "stdout" && stdout {
  2039. fmt.Fprintf(job.Stdout, "%s", logLine)
  2040. }
  2041. if l.Stream == "stderr" && stderr {
  2042. fmt.Fprintf(job.Stderr, "%s", logLine)
  2043. }
  2044. }
  2045. }
  2046. if follow {
  2047. errors := make(chan error, 2)
  2048. if stdout {
  2049. stdoutPipe := container.StdoutLogPipe()
  2050. go func() {
  2051. errors <- utils.WriteLog(stdoutPipe, job.Stdout, format)
  2052. }()
  2053. }
  2054. if stderr {
  2055. stderrPipe := container.StderrLogPipe()
  2056. go func() {
  2057. errors <- utils.WriteLog(stderrPipe, job.Stderr, format)
  2058. }()
  2059. }
  2060. err := <-errors
  2061. if err != nil {
  2062. utils.Errorf("%s", err)
  2063. }
  2064. }
  2065. return engine.StatusOK
  2066. }
  2067. func (srv *Server) ContainerAttach(job *engine.Job) engine.Status {
  2068. if len(job.Args) != 1 {
  2069. return job.Errorf("Usage: %s CONTAINER\n", job.Name)
  2070. }
  2071. var (
  2072. name = job.Args[0]
  2073. logs = job.GetenvBool("logs")
  2074. stream = job.GetenvBool("stream")
  2075. stdin = job.GetenvBool("stdin")
  2076. stdout = job.GetenvBool("stdout")
  2077. stderr = job.GetenvBool("stderr")
  2078. )
  2079. container := srv.daemon.Get(name)
  2080. if container == nil {
  2081. return job.Errorf("No such container: %s", name)
  2082. }
  2083. //logs
  2084. if logs {
  2085. cLog, err := container.ReadLog("json")
  2086. if err != nil && os.IsNotExist(err) {
  2087. // Legacy logs
  2088. utils.Debugf("Old logs format")
  2089. if stdout {
  2090. cLog, err := container.ReadLog("stdout")
  2091. if err != nil {
  2092. utils.Errorf("Error reading logs (stdout): %s", err)
  2093. } else if _, err := io.Copy(job.Stdout, cLog); err != nil {
  2094. utils.Errorf("Error streaming logs (stdout): %s", err)
  2095. }
  2096. }
  2097. if stderr {
  2098. cLog, err := container.ReadLog("stderr")
  2099. if err != nil {
  2100. utils.Errorf("Error reading logs (stderr): %s", err)
  2101. } else if _, err := io.Copy(job.Stderr, cLog); err != nil {
  2102. utils.Errorf("Error streaming logs (stderr): %s", err)
  2103. }
  2104. }
  2105. } else if err != nil {
  2106. utils.Errorf("Error reading logs (json): %s", err)
  2107. } else {
  2108. dec := json.NewDecoder(cLog)
  2109. for {
  2110. l := &utils.JSONLog{}
  2111. if err := dec.Decode(l); err == io.EOF {
  2112. break
  2113. } else if err != nil {
  2114. utils.Errorf("Error streaming logs: %s", err)
  2115. break
  2116. }
  2117. if l.Stream == "stdout" && stdout {
  2118. fmt.Fprintf(job.Stdout, "%s", l.Log)
  2119. }
  2120. if l.Stream == "stderr" && stderr {
  2121. fmt.Fprintf(job.Stderr, "%s", l.Log)
  2122. }
  2123. }
  2124. }
  2125. }
  2126. //stream
  2127. if stream {
  2128. var (
  2129. cStdin io.ReadCloser
  2130. cStdout, cStderr io.Writer
  2131. cStdinCloser io.Closer
  2132. )
  2133. if stdin {
  2134. r, w := io.Pipe()
  2135. go func() {
  2136. defer w.Close()
  2137. defer utils.Debugf("Closing buffered stdin pipe")
  2138. io.Copy(w, job.Stdin)
  2139. }()
  2140. cStdin = r
  2141. cStdinCloser = job.Stdin
  2142. }
  2143. if stdout {
  2144. cStdout = job.Stdout
  2145. }
  2146. if stderr {
  2147. cStderr = job.Stderr
  2148. }
  2149. <-srv.daemon.Attach(container, cStdin, cStdinCloser, cStdout, cStderr)
  2150. // If we are in stdinonce mode, wait for the process to end
  2151. // otherwise, simply return
  2152. if container.Config.StdinOnce && !container.Config.Tty {
  2153. container.Wait()
  2154. }
  2155. }
  2156. return engine.StatusOK
  2157. }
  2158. func (srv *Server) ContainerInspect(name string) (*daemon.Container, error) {
  2159. if container := srv.daemon.Get(name); container != nil {
  2160. return container, nil
  2161. }
  2162. return nil, fmt.Errorf("No such container: %s", name)
  2163. }
  2164. func (srv *Server) ImageInspect(name string) (*image.Image, error) {
  2165. if image, err := srv.daemon.Repositories().LookupImage(name); err == nil && image != nil {
  2166. return image, nil
  2167. }
  2168. return nil, fmt.Errorf("No such image: %s", name)
  2169. }
  2170. func (srv *Server) JobInspect(job *engine.Job) engine.Status {
  2171. // TODO: deprecate KIND/conflict
  2172. if n := len(job.Args); n != 2 {
  2173. return job.Errorf("Usage: %s CONTAINER|IMAGE KIND", job.Name)
  2174. }
  2175. var (
  2176. name = job.Args[0]
  2177. kind = job.Args[1]
  2178. object interface{}
  2179. conflict = job.GetenvBool("conflict") //should the job detect conflict between containers and images
  2180. image, errImage = srv.ImageInspect(name)
  2181. container, errContainer = srv.ContainerInspect(name)
  2182. )
  2183. if conflict && image != nil && container != nil {
  2184. return job.Errorf("Conflict between containers and images")
  2185. }
  2186. switch kind {
  2187. case "image":
  2188. if errImage != nil {
  2189. return job.Error(errImage)
  2190. }
  2191. object = image
  2192. case "container":
  2193. if errContainer != nil {
  2194. return job.Error(errContainer)
  2195. }
  2196. object = &struct {
  2197. *daemon.Container
  2198. HostConfig *runconfig.HostConfig
  2199. }{container, container.HostConfig()}
  2200. default:
  2201. return job.Errorf("Unknown kind: %s", kind)
  2202. }
  2203. b, err := json.Marshal(object)
  2204. if err != nil {
  2205. return job.Error(err)
  2206. }
  2207. job.Stdout.Write(b)
  2208. return engine.StatusOK
  2209. }
  2210. func (srv *Server) ContainerCopy(job *engine.Job) engine.Status {
  2211. if len(job.Args) != 2 {
  2212. return job.Errorf("Usage: %s CONTAINER RESOURCE\n", job.Name)
  2213. }
  2214. var (
  2215. name = job.Args[0]
  2216. resource = job.Args[1]
  2217. )
  2218. if container := srv.daemon.Get(name); container != nil {
  2219. data, err := container.Copy(resource)
  2220. if err != nil {
  2221. return job.Error(err)
  2222. }
  2223. defer data.Close()
  2224. if _, err := io.Copy(job.Stdout, data); err != nil {
  2225. return job.Error(err)
  2226. }
  2227. return engine.StatusOK
  2228. }
  2229. return job.Errorf("No such container: %s", name)
  2230. }
  2231. func NewServer(eng *engine.Engine, config *daemonconfig.Config) (*Server, error) {
  2232. daemon, err := daemon.NewDaemon(config, eng)
  2233. if err != nil {
  2234. return nil, err
  2235. }
  2236. srv := &Server{
  2237. Eng: eng,
  2238. daemon: daemon,
  2239. pullingPool: make(map[string]chan struct{}),
  2240. pushingPool: make(map[string]chan struct{}),
  2241. events: make([]utils.JSONMessage, 0, 64), //only keeps the 64 last events
  2242. listeners: make(map[string]chan utils.JSONMessage),
  2243. running: true,
  2244. }
  2245. daemon.SetServer(srv)
  2246. return srv, nil
  2247. }
  2248. func (srv *Server) LogEvent(action, id, from string) *utils.JSONMessage {
  2249. now := time.Now().UTC().Unix()
  2250. jm := utils.JSONMessage{Status: action, ID: id, From: from, Time: now}
  2251. srv.AddEvent(jm)
  2252. for _, c := range srv.listeners {
  2253. select { // non blocking channel
  2254. case c <- jm:
  2255. default:
  2256. }
  2257. }
  2258. return &jm
  2259. }
  2260. func (srv *Server) AddEvent(jm utils.JSONMessage) {
  2261. srv.Lock()
  2262. defer srv.Unlock()
  2263. srv.events = append(srv.events, jm)
  2264. }
  2265. func (srv *Server) GetEvents() []utils.JSONMessage {
  2266. srv.RLock()
  2267. defer srv.RUnlock()
  2268. return srv.events
  2269. }
  2270. func (srv *Server) SetRunning(status bool) {
  2271. srv.Lock()
  2272. defer srv.Unlock()
  2273. srv.running = status
  2274. }
  2275. func (srv *Server) IsRunning() bool {
  2276. srv.RLock()
  2277. defer srv.RUnlock()
  2278. return srv.running
  2279. }
  2280. func (srv *Server) Close() error {
  2281. if srv == nil {
  2282. return nil
  2283. }
  2284. srv.SetRunning(false)
  2285. if srv.daemon == nil {
  2286. return nil
  2287. }
  2288. return srv.daemon.Close()
  2289. }
  2290. type Server struct {
  2291. sync.RWMutex
  2292. daemon *daemon.Daemon
  2293. pullingPool map[string]chan struct{}
  2294. pushingPool map[string]chan struct{}
  2295. events []utils.JSONMessage
  2296. listeners map[string]chan utils.JSONMessage
  2297. Eng *engine.Engine
  2298. running bool
  2299. }