server.go 69 KB

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