server.go 71 KB

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