server.go 70 KB

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