server.go 66 KB

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