server.go 68 KB

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