server.go 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633
  1. package docker
  2. import (
  3. "bufio"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "github.com/dotcloud/docker/archive"
  8. "github.com/dotcloud/docker/auth"
  9. "github.com/dotcloud/docker/engine"
  10. "github.com/dotcloud/docker/gograph"
  11. "github.com/dotcloud/docker/registry"
  12. "github.com/dotcloud/docker/utils"
  13. "io"
  14. "io/ioutil"
  15. "log"
  16. "net/http"
  17. "net/url"
  18. "os"
  19. "os/exec"
  20. "os/signal"
  21. "path"
  22. "path/filepath"
  23. "runtime"
  24. "strings"
  25. "sync"
  26. "syscall"
  27. "time"
  28. )
  29. func (srv *Server) Close() error {
  30. return srv.runtime.Close()
  31. }
  32. func init() {
  33. engine.Register("initapi", jobInitApi)
  34. }
  35. // jobInitApi runs the remote api server `srv` as a daemon,
  36. // Only one api server can run at the same time - this is enforced by a pidfile.
  37. // The signals SIGINT, SIGKILL and SIGTERM are intercepted for cleanup.
  38. func jobInitApi(job *engine.Job) string {
  39. job.Logf("Creating server")
  40. srv, err := NewServer(job.Eng, ConfigFromJob(job))
  41. if err != nil {
  42. return err.Error()
  43. }
  44. if srv.runtime.config.Pidfile != "" {
  45. job.Logf("Creating pidfile")
  46. if err := utils.CreatePidFile(srv.runtime.config.Pidfile); err != nil {
  47. log.Fatal(err)
  48. }
  49. }
  50. job.Logf("Setting up signal traps")
  51. c := make(chan os.Signal, 1)
  52. signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
  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. job.Eng.Hack_SetGlobalVar("httpapi.bridgeIP", srv.runtime.networkManager.bridgeNetwork.IP)
  63. if err := job.Eng.Register("create", srv.ContainerCreate); err != nil {
  64. return err.Error()
  65. }
  66. if err := job.Eng.Register("start", srv.ContainerStart); err != nil {
  67. return err.Error()
  68. }
  69. if err := job.Eng.Register("serveapi", srv.ListenAndServe); err != nil {
  70. return err.Error()
  71. }
  72. return "0"
  73. }
  74. func (srv *Server) ListenAndServe(job *engine.Job) string {
  75. protoAddrs := job.Args
  76. chErrors := make(chan error, len(protoAddrs))
  77. for _, protoAddr := range protoAddrs {
  78. protoAddrParts := strings.SplitN(protoAddr, "://", 2)
  79. switch protoAddrParts[0] {
  80. case "unix":
  81. if err := syscall.Unlink(protoAddrParts[1]); err != nil && !os.IsNotExist(err) {
  82. log.Fatal(err)
  83. }
  84. case "tcp":
  85. if !strings.HasPrefix(protoAddrParts[1], "127.0.0.1") {
  86. log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
  87. }
  88. default:
  89. return "Invalid protocol format."
  90. }
  91. go func() {
  92. // FIXME: merge Server.ListenAndServe with ListenAndServe
  93. chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], srv, job.GetenvBool("Logging"))
  94. }()
  95. }
  96. for i := 0; i < len(protoAddrs); i += 1 {
  97. err := <-chErrors
  98. if err != nil {
  99. return err.Error()
  100. }
  101. }
  102. return "0"
  103. }
  104. func (srv *Server) DockerVersion() APIVersion {
  105. return APIVersion{
  106. Version: VERSION,
  107. GitCommit: GITCOMMIT,
  108. GoVersion: runtime.Version(),
  109. }
  110. }
  111. // simpleVersionInfo is a simple implementation of
  112. // the interface VersionInfo, which is used
  113. // to provide version information for some product,
  114. // component, etc. It stores the product name and the version
  115. // in string and returns them on calls to Name() and Version().
  116. type simpleVersionInfo struct {
  117. name string
  118. version string
  119. }
  120. func (v *simpleVersionInfo) Name() string {
  121. return v.name
  122. }
  123. func (v *simpleVersionInfo) Version() string {
  124. return v.version
  125. }
  126. // versionCheckers() returns version informations of:
  127. // docker, go, git-commit (of the docker) and the host's kernel.
  128. //
  129. // Such information will be used on call to NewRegistry().
  130. func (srv *Server) versionInfos() []utils.VersionInfo {
  131. v := srv.DockerVersion()
  132. ret := append(make([]utils.VersionInfo, 0, 4), &simpleVersionInfo{"docker", v.Version})
  133. if len(v.GoVersion) > 0 {
  134. ret = append(ret, &simpleVersionInfo{"go", v.GoVersion})
  135. }
  136. if len(v.GitCommit) > 0 {
  137. ret = append(ret, &simpleVersionInfo{"git-commit", v.GitCommit})
  138. }
  139. if kernelVersion, err := utils.GetKernelVersion(); err == nil {
  140. ret = append(ret, &simpleVersionInfo{"kernel", kernelVersion.String()})
  141. }
  142. return ret
  143. }
  144. // ContainerKill send signal to the container
  145. // If no signal is given (sig 0), then Kill with SIGKILL and wait
  146. // for the container to exit.
  147. // If a signal is given, then just send it to the container and return.
  148. func (srv *Server) ContainerKill(name string, sig int) error {
  149. if container := srv.runtime.Get(name); container != nil {
  150. // If no signal is passed, perform regular Kill (SIGKILL + wait())
  151. if sig == 0 {
  152. if err := container.Kill(); err != nil {
  153. return fmt.Errorf("Cannot kill container %s: %s", name, err)
  154. }
  155. srv.LogEvent("kill", container.ID, srv.runtime.repositories.ImageName(container.Image))
  156. } else {
  157. // Otherwise, just send the requested signal
  158. if err := container.kill(sig); err != nil {
  159. return fmt.Errorf("Cannot kill container %s: %s", name, err)
  160. }
  161. // FIXME: Add event for signals
  162. }
  163. } else {
  164. return fmt.Errorf("No such container: %s", name)
  165. }
  166. return nil
  167. }
  168. func (srv *Server) ContainerExport(name string, out io.Writer) error {
  169. if container := srv.runtime.Get(name); container != nil {
  170. data, err := container.Export()
  171. if err != nil {
  172. return err
  173. }
  174. // Stream the entire contents of the container (basically a volatile snapshot)
  175. if _, err := io.Copy(out, data); err != nil {
  176. return err
  177. }
  178. srv.LogEvent("export", container.ID, srv.runtime.repositories.ImageName(container.Image))
  179. return nil
  180. }
  181. return fmt.Errorf("No such container: %s", name)
  182. }
  183. func (srv *Server) ImagesSearch(term string) ([]registry.SearchResult, error) {
  184. r, err := registry.NewRegistry(srv.runtime.config.Root, nil, srv.HTTPRequestFactory(nil))
  185. if err != nil {
  186. return nil, err
  187. }
  188. results, err := r.SearchRepositories(term)
  189. if err != nil {
  190. return nil, err
  191. }
  192. return results.Results, nil
  193. }
  194. func (srv *Server) ImageInsert(name, url, path string, out io.Writer, sf *utils.StreamFormatter) error {
  195. out = utils.NewWriteFlusher(out)
  196. img, err := srv.runtime.repositories.LookupImage(name)
  197. if err != nil {
  198. return err
  199. }
  200. file, err := utils.Download(url, out)
  201. if err != nil {
  202. return err
  203. }
  204. defer file.Body.Close()
  205. config, _, _, err := ParseRun([]string{img.ID, "echo", "insert", url, path}, srv.runtime.capabilities)
  206. if err != nil {
  207. return err
  208. }
  209. c, _, err := srv.runtime.Create(config, "")
  210. if err != nil {
  211. return err
  212. }
  213. if err := c.Inject(utils.ProgressReader(file.Body, int(file.ContentLength), out, sf.FormatProgress("", "Downloading", "%8v/%v (%v)"), sf, false), path); err != nil {
  214. return err
  215. }
  216. // FIXME: Handle custom repo, tag comment, author
  217. img, err = srv.runtime.Commit(c, "", "", img.Comment, img.Author, nil)
  218. if err != nil {
  219. return err
  220. }
  221. out.Write(sf.FormatStatus(img.ID, ""))
  222. return nil
  223. }
  224. func (srv *Server) ImagesViz(out io.Writer) error {
  225. images, _ := srv.runtime.graph.Map()
  226. if images == nil {
  227. return nil
  228. }
  229. out.Write([]byte("digraph docker {\n"))
  230. var (
  231. parentImage *Image
  232. err error
  233. )
  234. for _, image := range images {
  235. parentImage, err = image.GetParent()
  236. if err != nil {
  237. return fmt.Errorf("Error while getting parent image: %v", err)
  238. }
  239. if parentImage != nil {
  240. out.Write([]byte(" \"" + parentImage.ID + "\" -> \"" + image.ID + "\"\n"))
  241. } else {
  242. out.Write([]byte(" base -> \"" + image.ID + "\" [style=invis]\n"))
  243. }
  244. }
  245. reporefs := make(map[string][]string)
  246. for name, repository := range srv.runtime.repositories.Repositories {
  247. for tag, id := range repository {
  248. reporefs[utils.TruncateID(id)] = append(reporefs[utils.TruncateID(id)], fmt.Sprintf("%s:%s", name, tag))
  249. }
  250. }
  251. for id, repos := range reporefs {
  252. out.Write([]byte(" \"" + id + "\" [label=\"" + id + "\\n" + strings.Join(repos, "\\n") + "\",shape=box,fillcolor=\"paleturquoise\",style=\"filled,rounded\"];\n"))
  253. }
  254. out.Write([]byte(" base [style=invisible]\n}\n"))
  255. return nil
  256. }
  257. func (srv *Server) Images(all bool, filter string) ([]APIImages, error) {
  258. var (
  259. allImages map[string]*Image
  260. err error
  261. )
  262. if all {
  263. allImages, err = srv.runtime.graph.Map()
  264. } else {
  265. allImages, err = srv.runtime.graph.Heads()
  266. }
  267. if err != nil {
  268. return nil, err
  269. }
  270. lookup := make(map[string]APIImages)
  271. for name, repository := range srv.runtime.repositories.Repositories {
  272. if filter != "" {
  273. if match, _ := path.Match(filter, name); !match {
  274. continue
  275. }
  276. }
  277. for tag, id := range repository {
  278. image, err := srv.runtime.graph.Get(id)
  279. if err != nil {
  280. log.Printf("Warning: couldn't load %s from %s/%s: %s", id, name, tag, err)
  281. continue
  282. }
  283. if out, exists := lookup[id]; exists {
  284. out.RepoTags = append(out.RepoTags, fmt.Sprintf("%s:%s", name, tag))
  285. lookup[id] = out
  286. } else {
  287. var out APIImages
  288. delete(allImages, id)
  289. out.ParentId = image.Parent
  290. out.RepoTags = []string{fmt.Sprintf("%s:%s", name, tag)}
  291. out.ID = image.ID
  292. out.Created = image.Created.Unix()
  293. out.Size = image.Size
  294. out.VirtualSize = image.getParentsSize(0) + image.Size
  295. lookup[id] = out
  296. }
  297. }
  298. }
  299. outs := make([]APIImages, 0, len(lookup))
  300. for _, value := range lookup {
  301. outs = append(outs, value)
  302. }
  303. // Display images which aren't part of a repository/tag
  304. if filter == "" {
  305. for _, image := range allImages {
  306. var out APIImages
  307. out.ID = image.ID
  308. out.ParentId = image.Parent
  309. out.RepoTags = []string{"<none>:<none>"}
  310. out.Created = image.Created.Unix()
  311. out.Size = image.Size
  312. out.VirtualSize = image.getParentsSize(0) + image.Size
  313. outs = append(outs, out)
  314. }
  315. }
  316. sortImagesByCreationAndTag(outs)
  317. return outs, nil
  318. }
  319. func (srv *Server) DockerInfo() *APIInfo {
  320. images, _ := srv.runtime.graph.Map()
  321. var imgcount int
  322. if images == nil {
  323. imgcount = 0
  324. } else {
  325. imgcount = len(images)
  326. }
  327. lxcVersion := ""
  328. if output, err := exec.Command("lxc-version").CombinedOutput(); err == nil {
  329. outputStr := string(output)
  330. if len(strings.SplitN(outputStr, ":", 2)) == 2 {
  331. lxcVersion = strings.TrimSpace(strings.SplitN(string(output), ":", 2)[1])
  332. }
  333. }
  334. kernelVersion := "<unknown>"
  335. if kv, err := utils.GetKernelVersion(); err == nil {
  336. kernelVersion = kv.String()
  337. }
  338. return &APIInfo{
  339. Containers: len(srv.runtime.List()),
  340. Images: imgcount,
  341. MemoryLimit: srv.runtime.capabilities.MemoryLimit,
  342. SwapLimit: srv.runtime.capabilities.SwapLimit,
  343. IPv4Forwarding: !srv.runtime.capabilities.IPv4ForwardingDisabled,
  344. Debug: os.Getenv("DEBUG") != "",
  345. NFd: utils.GetTotalUsedFds(),
  346. NGoroutines: runtime.NumGoroutine(),
  347. LXCVersion: lxcVersion,
  348. NEventsListener: len(srv.events),
  349. KernelVersion: kernelVersion,
  350. IndexServerAddress: auth.IndexServerAddress(),
  351. }
  352. }
  353. func (srv *Server) ImageHistory(name string) ([]APIHistory, error) {
  354. image, err := srv.runtime.repositories.LookupImage(name)
  355. if err != nil {
  356. return nil, err
  357. }
  358. lookupMap := make(map[string][]string)
  359. for name, repository := range srv.runtime.repositories.Repositories {
  360. for tag, id := range repository {
  361. // If the ID already has a reverse lookup, do not update it unless for "latest"
  362. if _, exists := lookupMap[id]; !exists {
  363. lookupMap[id] = []string{}
  364. }
  365. lookupMap[id] = append(lookupMap[id], name+":"+tag)
  366. }
  367. }
  368. outs := []APIHistory{} //produce [] when empty instead of 'null'
  369. err = image.WalkHistory(func(img *Image) error {
  370. var out APIHistory
  371. out.ID = img.ID
  372. out.Created = img.Created.Unix()
  373. out.CreatedBy = strings.Join(img.ContainerConfig.Cmd, " ")
  374. out.Tags = lookupMap[img.ID]
  375. out.Size = img.Size
  376. outs = append(outs, out)
  377. return nil
  378. })
  379. return outs, nil
  380. }
  381. func (srv *Server) ContainerTop(name, ps_args string) (*APITop, error) {
  382. if container := srv.runtime.Get(name); container != nil {
  383. output, err := exec.Command("lxc-ps", "--name", container.ID, "--", ps_args).CombinedOutput()
  384. if err != nil {
  385. return nil, fmt.Errorf("lxc-ps: %s (%s)", err, output)
  386. }
  387. procs := APITop{}
  388. for i, line := range strings.Split(string(output), "\n") {
  389. if len(line) == 0 {
  390. continue
  391. }
  392. words := []string{}
  393. scanner := bufio.NewScanner(strings.NewReader(line))
  394. scanner.Split(bufio.ScanWords)
  395. if !scanner.Scan() {
  396. return nil, fmt.Errorf("Wrong output using lxc-ps")
  397. }
  398. // no scanner.Text because we skip container id
  399. for scanner.Scan() {
  400. if i != 0 && len(words) == len(procs.Titles) {
  401. words[len(words)-1] = fmt.Sprintf("%s %s", words[len(words)-1], scanner.Text())
  402. } else {
  403. words = append(words, scanner.Text())
  404. }
  405. }
  406. if i == 0 {
  407. procs.Titles = words
  408. } else {
  409. procs.Processes = append(procs.Processes, words)
  410. }
  411. }
  412. return &procs, nil
  413. }
  414. return nil, fmt.Errorf("No such container: %s", name)
  415. }
  416. func (srv *Server) ContainerChanges(name string) ([]Change, error) {
  417. if container := srv.runtime.Get(name); container != nil {
  418. return container.Changes()
  419. }
  420. return nil, fmt.Errorf("No such container: %s", name)
  421. }
  422. func (srv *Server) Containers(all, size bool, n int, since, before string) []APIContainers {
  423. var foundBefore bool
  424. var displayed int
  425. out := []APIContainers{}
  426. for _, container := range srv.runtime.List() {
  427. if !container.State.Running && !all && n == -1 && since == "" && before == "" {
  428. continue
  429. }
  430. if before != "" {
  431. if container.ID == before || utils.TruncateID(container.ID) == before {
  432. foundBefore = true
  433. continue
  434. }
  435. if !foundBefore {
  436. continue
  437. }
  438. }
  439. if displayed == n {
  440. break
  441. }
  442. if container.ID == since || utils.TruncateID(container.ID) == since {
  443. break
  444. }
  445. displayed++
  446. c := createAPIContainer(container, size, srv.runtime)
  447. out = append(out, c)
  448. }
  449. return out
  450. }
  451. func createAPIContainer(container *Container, size bool, runtime *Runtime) APIContainers {
  452. c := APIContainers{
  453. ID: container.ID,
  454. }
  455. names := []string{}
  456. runtime.containerGraph.Walk("/", func(p string, e *gograph.Entity) error {
  457. if e.ID() == container.ID {
  458. names = append(names, p)
  459. }
  460. return nil
  461. }, -1)
  462. c.Names = names
  463. c.Image = runtime.repositories.ImageName(container.Image)
  464. c.Command = fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " "))
  465. c.Created = container.Created.Unix()
  466. c.Status = container.State.String()
  467. c.Ports = container.NetworkSettings.PortMappingAPI()
  468. if size {
  469. c.SizeRw, c.SizeRootFs = container.GetSize()
  470. }
  471. return c
  472. }
  473. func (srv *Server) ContainerCommit(name, repo, tag, author, comment string, config *Config) (string, error) {
  474. container := srv.runtime.Get(name)
  475. if container == nil {
  476. return "", fmt.Errorf("No such container: %s", name)
  477. }
  478. img, err := srv.runtime.Commit(container, repo, tag, comment, author, config)
  479. if err != nil {
  480. return "", err
  481. }
  482. return img.ID, err
  483. }
  484. // FIXME: this should be called ImageTag
  485. func (srv *Server) ContainerTag(name, repo, tag string, force bool) error {
  486. if err := srv.runtime.repositories.Set(repo, tag, name, force); err != nil {
  487. return err
  488. }
  489. return nil
  490. }
  491. func (srv *Server) pullImage(r *registry.Registry, out io.Writer, imgID, endpoint string, token []string, sf *utils.StreamFormatter) error {
  492. history, err := r.GetRemoteHistory(imgID, endpoint, token)
  493. if err != nil {
  494. return err
  495. }
  496. out.Write(sf.FormatProgress(utils.TruncateID(imgID), "Pulling", "dependend layers"))
  497. // FIXME: Try to stream the images?
  498. // FIXME: Launch the getRemoteImage() in goroutines
  499. for _, id := range history {
  500. // ensure no two downloads of the same layer happen at the same time
  501. if err := srv.poolAdd("pull", "layer:"+id); err != nil {
  502. utils.Errorf("Image (id: %s) pull is already running, skipping: %v", id, err)
  503. return nil
  504. }
  505. defer srv.poolRemove("pull", "layer:"+id)
  506. if !srv.runtime.graph.Exists(id) {
  507. out.Write(sf.FormatProgress(utils.TruncateID(id), "Pulling", "metadata"))
  508. imgJSON, imgSize, err := r.GetRemoteImageJSON(id, endpoint, token)
  509. if err != nil {
  510. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error", "pulling dependend layers"))
  511. // FIXME: Keep going in case of error?
  512. return err
  513. }
  514. img, err := NewImgJSON(imgJSON)
  515. if err != nil {
  516. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error", "pulling dependend layers"))
  517. return fmt.Errorf("Failed to parse json: %s", err)
  518. }
  519. // Get the layer
  520. out.Write(sf.FormatProgress(utils.TruncateID(id), "Pulling", "fs layer"))
  521. layer, err := r.GetRemoteImageLayer(img.ID, endpoint, token)
  522. if err != nil {
  523. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error", "pulling dependend layers"))
  524. return err
  525. }
  526. defer layer.Close()
  527. if err := srv.runtime.graph.Register(imgJSON, utils.ProgressReader(layer, imgSize, out, sf.FormatProgress(utils.TruncateID(id), "Downloading", "%8v/%v (%v)"), sf, false), img); err != nil {
  528. out.Write(sf.FormatProgress(utils.TruncateID(id), "Error", "downloading dependend layers"))
  529. return err
  530. }
  531. }
  532. out.Write(sf.FormatProgress(utils.TruncateID(id), "Download", "complete"))
  533. }
  534. return nil
  535. }
  536. func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, localName, remoteName, askedTag, indexEp string, sf *utils.StreamFormatter, parallel bool) error {
  537. out.Write(sf.FormatStatus("", "Pulling repository %s", localName))
  538. repoData, err := r.GetRepositoryData(indexEp, remoteName)
  539. if err != nil {
  540. return err
  541. }
  542. utils.Debugf("Retrieving the tag list")
  543. tagsList, err := r.GetRemoteTags(repoData.Endpoints, remoteName, repoData.Tokens)
  544. if err != nil {
  545. utils.Errorf("%v", err)
  546. return err
  547. }
  548. for tag, id := range tagsList {
  549. repoData.ImgList[id] = &registry.ImgData{
  550. ID: id,
  551. Tag: tag,
  552. Checksum: "",
  553. }
  554. }
  555. utils.Debugf("Registering tags")
  556. // If no tag has been specified, pull them all
  557. if askedTag == "" {
  558. for tag, id := range tagsList {
  559. repoData.ImgList[id].Tag = tag
  560. }
  561. } else {
  562. // Otherwise, check that the tag exists and use only that one
  563. id, exists := tagsList[askedTag]
  564. if !exists {
  565. return fmt.Errorf("Tag %s not found in repository %s", askedTag, localName)
  566. }
  567. repoData.ImgList[id].Tag = askedTag
  568. }
  569. errors := make(chan error)
  570. for _, image := range repoData.ImgList {
  571. downloadImage := func(img *registry.ImgData) {
  572. if askedTag != "" && img.Tag != askedTag {
  573. utils.Debugf("(%s) does not match %s (id: %s), skipping", img.Tag, askedTag, img.ID)
  574. if parallel {
  575. errors <- nil
  576. }
  577. return
  578. }
  579. if img.Tag == "" {
  580. utils.Debugf("Image (id: %s) present in this repository but untagged, skipping", img.ID)
  581. if parallel {
  582. errors <- nil
  583. }
  584. return
  585. }
  586. // ensure no two downloads of the same image happen at the same time
  587. if err := srv.poolAdd("pull", "img:"+img.ID); err != nil {
  588. utils.Errorf("Image (id: %s) pull is already running, skipping: %v", img.ID, err)
  589. if parallel {
  590. errors <- nil
  591. }
  592. return
  593. }
  594. defer srv.poolRemove("pull", "img:"+img.ID)
  595. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Pulling", fmt.Sprintf("image (%s) from %s", img.Tag, localName)))
  596. success := false
  597. var lastErr error
  598. for _, ep := range repoData.Endpoints {
  599. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Pulling", fmt.Sprintf("image (%s) from %s, endpoint: %s", img.Tag, localName, ep)))
  600. if err := srv.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
  601. // Its not ideal that only the last error is returned, it would be better to concatenate the errors.
  602. // As the error is also given to the output stream the user will see the error.
  603. lastErr = err
  604. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Error pulling", fmt.Sprintf("image (%s) from %s, endpoint: %s, %s", img.Tag, localName, ep, err)))
  605. continue
  606. }
  607. success = true
  608. break
  609. }
  610. if !success {
  611. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Error pulling", fmt.Sprintf("image (%s) from %s, %s", img.Tag, localName, lastErr)))
  612. if parallel {
  613. errors <- fmt.Errorf("Could not find repository on any of the indexed registries.")
  614. return
  615. }
  616. }
  617. out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Download", "complete"))
  618. if parallel {
  619. errors <- nil
  620. }
  621. }
  622. if parallel {
  623. go downloadImage(image)
  624. } else {
  625. downloadImage(image)
  626. }
  627. }
  628. if parallel {
  629. var lastError error
  630. for i := 0; i < len(repoData.ImgList); i++ {
  631. if err := <-errors; err != nil {
  632. lastError = err
  633. }
  634. }
  635. if lastError != nil {
  636. return lastError
  637. }
  638. }
  639. for tag, id := range tagsList {
  640. if askedTag != "" && tag != askedTag {
  641. continue
  642. }
  643. if err := srv.runtime.repositories.Set(localName, tag, id, true); err != nil {
  644. return err
  645. }
  646. }
  647. if err := srv.runtime.repositories.Save(); err != nil {
  648. return err
  649. }
  650. return nil
  651. }
  652. func (srv *Server) poolAdd(kind, key string) error {
  653. srv.Lock()
  654. defer srv.Unlock()
  655. if _, exists := srv.pullingPool[key]; exists {
  656. return fmt.Errorf("pull %s is already in progress", key)
  657. }
  658. if _, exists := srv.pushingPool[key]; exists {
  659. return fmt.Errorf("push %s is already in progress", key)
  660. }
  661. switch kind {
  662. case "pull":
  663. srv.pullingPool[key] = struct{}{}
  664. break
  665. case "push":
  666. srv.pushingPool[key] = struct{}{}
  667. break
  668. default:
  669. return fmt.Errorf("Unknown pool type")
  670. }
  671. return nil
  672. }
  673. func (srv *Server) poolRemove(kind, key string) error {
  674. switch kind {
  675. case "pull":
  676. delete(srv.pullingPool, key)
  677. break
  678. case "push":
  679. delete(srv.pushingPool, key)
  680. break
  681. default:
  682. return fmt.Errorf("Unknown pool type")
  683. }
  684. return nil
  685. }
  686. func (srv *Server) ImagePull(localName string, tag string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig, metaHeaders map[string][]string, parallel bool) error {
  687. r, err := registry.NewRegistry(srv.runtime.config.Root, authConfig, srv.HTTPRequestFactory(metaHeaders))
  688. if err != nil {
  689. return err
  690. }
  691. if err := srv.poolAdd("pull", localName+":"+tag); err != nil {
  692. return err
  693. }
  694. defer srv.poolRemove("pull", localName+":"+tag)
  695. // Resolve the Repository name from fqn to endpoint + name
  696. endpoint, remoteName, err := registry.ResolveRepositoryName(localName)
  697. if err != nil {
  698. return err
  699. }
  700. if endpoint == auth.IndexServerAddress() {
  701. // If pull "index.docker.io/foo/bar", it's stored locally under "foo/bar"
  702. localName = remoteName
  703. }
  704. out = utils.NewWriteFlusher(out)
  705. err = srv.pullRepository(r, out, localName, remoteName, tag, endpoint, sf, parallel)
  706. if err == registry.ErrLoginRequired {
  707. return err
  708. }
  709. if err != nil {
  710. if err := srv.pullImage(r, out, remoteName, endpoint, nil, sf); err != nil {
  711. return err
  712. }
  713. return nil
  714. }
  715. return nil
  716. }
  717. // Retrieve the all the images to be uploaded in the correct order
  718. // Note: we can't use a map as it is not ordered
  719. func (srv *Server) getImageList(localRepo map[string]string) ([][]*registry.ImgData, error) {
  720. imgList := map[string]*registry.ImgData{}
  721. depGraph := utils.NewDependencyGraph()
  722. for tag, id := range localRepo {
  723. img, err := srv.runtime.graph.Get(id)
  724. if err != nil {
  725. return nil, err
  726. }
  727. depGraph.NewNode(img.ID)
  728. img.WalkHistory(func(current *Image) error {
  729. imgList[current.ID] = &registry.ImgData{
  730. ID: current.ID,
  731. Tag: tag,
  732. }
  733. parent, err := current.GetParent()
  734. if err != nil {
  735. return err
  736. }
  737. if parent == nil {
  738. return nil
  739. }
  740. depGraph.NewNode(parent.ID)
  741. depGraph.AddDependency(current.ID, parent.ID)
  742. return nil
  743. })
  744. }
  745. traversalMap, err := depGraph.GenerateTraversalMap()
  746. if err != nil {
  747. return nil, err
  748. }
  749. utils.Debugf("Traversal map: %v", traversalMap)
  750. result := [][]*registry.ImgData{}
  751. for _, round := range traversalMap {
  752. dataRound := []*registry.ImgData{}
  753. for _, imgID := range round {
  754. dataRound = append(dataRound, imgList[imgID])
  755. }
  756. result = append(result, dataRound)
  757. }
  758. return result, nil
  759. }
  760. func flatten(slc [][]*registry.ImgData) []*registry.ImgData {
  761. result := []*registry.ImgData{}
  762. for _, x := range slc {
  763. result = append(result, x...)
  764. }
  765. return result
  766. }
  767. func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, localName, remoteName string, localRepo map[string]string, indexEp string, sf *utils.StreamFormatter) error {
  768. out = utils.NewWriteFlusher(out)
  769. imgList, err := srv.getImageList(localRepo)
  770. if err != nil {
  771. return err
  772. }
  773. flattenedImgList := flatten(imgList)
  774. out.Write(sf.FormatStatus("", "Sending image list"))
  775. var repoData *registry.RepositoryData
  776. repoData, err = r.PushImageJSONIndex(indexEp, remoteName, flattenedImgList, false, nil)
  777. if err != nil {
  778. return err
  779. }
  780. for _, ep := range repoData.Endpoints {
  781. out.Write(sf.FormatStatus("", "Pushing repository %s (%d tags)", localName, len(localRepo)))
  782. // This section can not be parallelized (each round depends on the previous one)
  783. for _, round := range imgList {
  784. // FIXME: This section can be parallelized
  785. for _, elem := range round {
  786. var pushTags func() error
  787. pushTags = func() error {
  788. out.Write(sf.FormatStatus("", "Pushing tags for rev [%s] on {%s}", elem.ID, ep+"repositories/"+remoteName+"/tags/"+elem.Tag))
  789. if err := r.PushRegistryTag(remoteName, elem.ID, elem.Tag, ep, repoData.Tokens); err != nil {
  790. return err
  791. }
  792. return nil
  793. }
  794. if _, exists := repoData.ImgList[elem.ID]; exists {
  795. if err := pushTags(); err != nil {
  796. return err
  797. }
  798. out.Write(sf.FormatStatus("", "Image %s already pushed, skipping", elem.ID))
  799. continue
  800. } else if r.LookupRemoteImage(elem.ID, ep, repoData.Tokens) {
  801. if err := pushTags(); err != nil {
  802. return err
  803. }
  804. out.Write(sf.FormatStatus("", "Image %s already pushed, skipping", elem.ID))
  805. continue
  806. }
  807. if checksum, err := srv.pushImage(r, out, remoteName, elem.ID, ep, repoData.Tokens, sf); err != nil {
  808. // FIXME: Continue on error?
  809. return err
  810. } else {
  811. elem.Checksum = checksum
  812. }
  813. if err := pushTags(); err != nil {
  814. return err
  815. }
  816. }
  817. }
  818. }
  819. if _, err := r.PushImageJSONIndex(indexEp, remoteName, flattenedImgList, true, repoData.Endpoints); err != nil {
  820. return err
  821. }
  822. return nil
  823. }
  824. func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgID, ep string, token []string, sf *utils.StreamFormatter) (checksum string, err error) {
  825. out = utils.NewWriteFlusher(out)
  826. jsonRaw, err := ioutil.ReadFile(path.Join(srv.runtime.graph.Root, imgID, "json"))
  827. if err != nil {
  828. return "", fmt.Errorf("Cannot retrieve the path for {%s}: %s", imgID, err)
  829. }
  830. out.Write(sf.FormatStatus("", "Pushing %s", imgID))
  831. imgData := &registry.ImgData{
  832. ID: imgID,
  833. }
  834. // Send the json
  835. if err := r.PushImageJSONRegistry(imgData, jsonRaw, ep, token); err != nil {
  836. if err == registry.ErrAlreadyExists {
  837. out.Write(sf.FormatStatus("", "Image %s already pushed, skipping", imgData.ID))
  838. return "", nil
  839. }
  840. return "", err
  841. }
  842. layerData, err := srv.runtime.graph.TempLayerArchive(imgID, archive.Uncompressed, sf, out)
  843. if err != nil {
  844. return "", fmt.Errorf("Failed to generate layer archive: %s", err)
  845. }
  846. // Send the layer
  847. if checksum, err := r.PushImageLayerRegistry(imgData.ID, utils.ProgressReader(layerData, int(layerData.Size), out, sf.FormatProgress("", "Pushing", "%8v/%v (%v)"), sf, false), ep, token, jsonRaw); err != nil {
  848. return "", err
  849. } else {
  850. imgData.Checksum = checksum
  851. }
  852. out.Write(sf.FormatStatus("", ""))
  853. // Send the checksum
  854. if err := r.PushImageChecksumRegistry(imgData, ep, token); err != nil {
  855. return "", err
  856. }
  857. return imgData.Checksum, nil
  858. }
  859. // FIXME: Allow to interrupt current push when new push of same image is done.
  860. func (srv *Server) ImagePush(localName string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig, metaHeaders map[string][]string) error {
  861. if err := srv.poolAdd("push", localName); err != nil {
  862. return err
  863. }
  864. defer srv.poolRemove("push", localName)
  865. // Resolve the Repository name from fqn to endpoint + name
  866. endpoint, remoteName, err := registry.ResolveRepositoryName(localName)
  867. if err != nil {
  868. return err
  869. }
  870. out = utils.NewWriteFlusher(out)
  871. img, err := srv.runtime.graph.Get(localName)
  872. r, err2 := registry.NewRegistry(srv.runtime.config.Root, authConfig, srv.HTTPRequestFactory(metaHeaders))
  873. if err2 != nil {
  874. return err2
  875. }
  876. if err != nil {
  877. reposLen := len(srv.runtime.repositories.Repositories[localName])
  878. out.Write(sf.FormatStatus("", "The push refers to a repository [%s] (len: %d)", localName, reposLen))
  879. // If it fails, try to get the repository
  880. if localRepo, exists := srv.runtime.repositories.Repositories[localName]; exists {
  881. if err := srv.pushRepository(r, out, localName, remoteName, localRepo, endpoint, sf); err != nil {
  882. return err
  883. }
  884. return nil
  885. }
  886. return err
  887. }
  888. var token []string
  889. out.Write(sf.FormatStatus("", "The push refers to an image: [%s]", localName))
  890. if _, err := srv.pushImage(r, out, remoteName, img.ID, endpoint, token, sf); err != nil {
  891. return err
  892. }
  893. return nil
  894. }
  895. func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Writer, sf *utils.StreamFormatter) error {
  896. var archive io.Reader
  897. var resp *http.Response
  898. if src == "-" {
  899. archive = in
  900. } else {
  901. u, err := url.Parse(src)
  902. if err != nil {
  903. return err
  904. }
  905. if u.Scheme == "" {
  906. u.Scheme = "http"
  907. u.Host = src
  908. u.Path = ""
  909. }
  910. out.Write(sf.FormatStatus("", "Downloading from %s", u))
  911. // Download with curl (pretty progress bar)
  912. // If curl is not available, fallback to http.Get()
  913. resp, err = utils.Download(u.String(), out)
  914. if err != nil {
  915. return err
  916. }
  917. archive = utils.ProgressReader(resp.Body, int(resp.ContentLength), out, sf.FormatProgress("", "Importing", "%8v/%v (%v)"), sf, true)
  918. }
  919. img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src, "", nil)
  920. if err != nil {
  921. return err
  922. }
  923. // Optionally register the image at REPO/TAG
  924. if repo != "" {
  925. if err := srv.runtime.repositories.Set(repo, tag, img.ID, true); err != nil {
  926. return err
  927. }
  928. }
  929. out.Write(sf.FormatStatus("", img.ID))
  930. return nil
  931. }
  932. func (srv *Server) ContainerCreate(job *engine.Job) string {
  933. var name string
  934. if len(job.Args) == 1 {
  935. name = job.Args[0]
  936. } else if len(job.Args) > 1 {
  937. return fmt.Sprintf("Usage: %s ", job.Name)
  938. }
  939. var config Config
  940. if err := job.ExportEnv(&config); err != nil {
  941. return err.Error()
  942. }
  943. if config.Memory != 0 && config.Memory < 524288 {
  944. return "Minimum memory limit allowed is 512k"
  945. }
  946. if config.Memory > 0 && !srv.runtime.capabilities.MemoryLimit {
  947. config.Memory = 0
  948. }
  949. if config.Memory > 0 && !srv.runtime.capabilities.SwapLimit {
  950. config.MemorySwap = -1
  951. }
  952. container, buildWarnings, err := srv.runtime.Create(&config, name)
  953. if err != nil {
  954. if srv.runtime.graph.IsNotExist(err) {
  955. _, tag := utils.ParseRepositoryTag(config.Image)
  956. if tag == "" {
  957. tag = DEFAULTTAG
  958. }
  959. return fmt.Sprintf("No such image: %s (tag: %s)", config.Image, tag)
  960. }
  961. return err.Error()
  962. }
  963. srv.LogEvent("create", container.ID, srv.runtime.repositories.ImageName(container.Image))
  964. // FIXME: this is necessary because runtime.Create might return a nil container
  965. // with a non-nil error. This should not happen! Once it's fixed we
  966. // can remove this workaround.
  967. if container != nil {
  968. job.Printf("%s\n", container.ID)
  969. }
  970. for _, warning := range buildWarnings {
  971. job.Errorf("%s\n", warning)
  972. }
  973. return "0"
  974. }
  975. func (srv *Server) ContainerRestart(name string, t int) error {
  976. if container := srv.runtime.Get(name); container != nil {
  977. if err := container.Restart(t); err != nil {
  978. return fmt.Errorf("Cannot restart container %s: %s", name, err)
  979. }
  980. srv.LogEvent("restart", container.ID, srv.runtime.repositories.ImageName(container.Image))
  981. } else {
  982. return fmt.Errorf("No such container: %s", name)
  983. }
  984. return nil
  985. }
  986. func (srv *Server) ContainerDestroy(name string, removeVolume, removeLink bool) error {
  987. container := srv.runtime.Get(name)
  988. if removeLink {
  989. if container == nil {
  990. return fmt.Errorf("No such link: %s", name)
  991. }
  992. name, err := srv.runtime.getFullName(name)
  993. if err != nil {
  994. return err
  995. }
  996. parent, n := path.Split(name)
  997. if parent == "/" {
  998. return fmt.Errorf("Conflict, cannot remove the default name of the container")
  999. }
  1000. pe := srv.runtime.containerGraph.Get(parent)
  1001. if pe == nil {
  1002. return fmt.Errorf("Cannot get parent %s for name %s", parent, name)
  1003. }
  1004. parentContainer := srv.runtime.Get(pe.ID())
  1005. if parentContainer != nil && parentContainer.activeLinks != nil {
  1006. if link, exists := parentContainer.activeLinks[n]; exists {
  1007. link.Disable()
  1008. } else {
  1009. utils.Debugf("Could not find active link for %s", name)
  1010. }
  1011. }
  1012. if err := srv.runtime.containerGraph.Delete(name); err != nil {
  1013. return err
  1014. }
  1015. return nil
  1016. }
  1017. if container != nil {
  1018. if container.State.Running {
  1019. return fmt.Errorf("Impossible to remove a running container, please stop it first")
  1020. }
  1021. volumes := make(map[string]struct{})
  1022. // Store all the deleted containers volumes
  1023. for _, volumeId := range container.Volumes {
  1024. volumeId = strings.TrimRight(volumeId, "/layer")
  1025. volumeId = filepath.Base(volumeId)
  1026. volumes[volumeId] = struct{}{}
  1027. }
  1028. if err := srv.runtime.Destroy(container); err != nil {
  1029. return fmt.Errorf("Cannot destroy container %s: %s", name, err)
  1030. }
  1031. srv.LogEvent("destroy", container.ID, srv.runtime.repositories.ImageName(container.Image))
  1032. if removeVolume {
  1033. // Retrieve all volumes from all remaining containers
  1034. usedVolumes := make(map[string]*Container)
  1035. for _, container := range srv.runtime.List() {
  1036. for _, containerVolumeId := range container.Volumes {
  1037. usedVolumes[containerVolumeId] = container
  1038. }
  1039. }
  1040. for volumeId := range volumes {
  1041. // If the requested volu
  1042. if c, exists := usedVolumes[volumeId]; exists {
  1043. log.Printf("The volume %s is used by the container %s. Impossible to remove it. Skipping.\n", volumeId, c.ID)
  1044. continue
  1045. }
  1046. if err := srv.runtime.volumes.Delete(volumeId); err != nil {
  1047. return err
  1048. }
  1049. }
  1050. }
  1051. } else {
  1052. return fmt.Errorf("No such container: %s", name)
  1053. }
  1054. return nil
  1055. }
  1056. var ErrImageReferenced = errors.New("Image referenced by a repository")
  1057. func (srv *Server) deleteImageAndChildren(id string, imgs *[]APIRmi) error {
  1058. // If the image is referenced by a repo, do not delete
  1059. if len(srv.runtime.repositories.ByID()[id]) != 0 {
  1060. return ErrImageReferenced
  1061. }
  1062. // If the image is not referenced but has children, go recursive
  1063. referenced := false
  1064. byParents, err := srv.runtime.graph.ByParent()
  1065. if err != nil {
  1066. return err
  1067. }
  1068. for _, img := range byParents[id] {
  1069. if err := srv.deleteImageAndChildren(img.ID, imgs); err != nil {
  1070. if err != ErrImageReferenced {
  1071. return err
  1072. }
  1073. referenced = true
  1074. }
  1075. }
  1076. if referenced {
  1077. return ErrImageReferenced
  1078. }
  1079. // If the image is not referenced and has no children, remove it
  1080. byParents, err = srv.runtime.graph.ByParent()
  1081. if err != nil {
  1082. return err
  1083. }
  1084. if len(byParents[id]) == 0 {
  1085. if err := srv.runtime.repositories.DeleteAll(id); err != nil {
  1086. return err
  1087. }
  1088. err := srv.runtime.graph.Delete(id)
  1089. if err != nil {
  1090. return err
  1091. }
  1092. *imgs = append(*imgs, APIRmi{Deleted: utils.TruncateID(id)})
  1093. srv.LogEvent("delete", utils.TruncateID(id), "")
  1094. return nil
  1095. }
  1096. return nil
  1097. }
  1098. func (srv *Server) deleteImageParents(img *Image, imgs *[]APIRmi) error {
  1099. if img.Parent != "" {
  1100. parent, err := srv.runtime.graph.Get(img.Parent)
  1101. if err != nil {
  1102. return err
  1103. }
  1104. // Remove all children images
  1105. if err := srv.deleteImageAndChildren(img.Parent, imgs); err != nil {
  1106. return err
  1107. }
  1108. return srv.deleteImageParents(parent, imgs)
  1109. }
  1110. return nil
  1111. }
  1112. func (srv *Server) deleteImage(img *Image, repoName, tag string) ([]APIRmi, error) {
  1113. imgs := []APIRmi{}
  1114. tags := []string{}
  1115. //If delete by id, see if the id belong only to one repository
  1116. if repoName == "" {
  1117. for _, repoAndTag := range srv.runtime.repositories.ByID()[img.ID] {
  1118. parsedRepo, parsedTag := utils.ParseRepositoryTag(repoAndTag)
  1119. if repoName == "" || repoName == parsedRepo {
  1120. repoName = parsedRepo
  1121. if parsedTag != "" {
  1122. tags = append(tags, parsedTag)
  1123. }
  1124. } else if repoName != parsedRepo {
  1125. // the id belongs to multiple repos, like base:latest and user:test,
  1126. // in that case return conflict
  1127. return imgs, nil
  1128. }
  1129. }
  1130. } else {
  1131. tags = append(tags, tag)
  1132. }
  1133. //Untag the current image
  1134. for _, tag := range tags {
  1135. tagDeleted, err := srv.runtime.repositories.Delete(repoName, tag)
  1136. if err != nil {
  1137. return nil, err
  1138. }
  1139. if tagDeleted {
  1140. imgs = append(imgs, APIRmi{Untagged: img.ID})
  1141. srv.LogEvent("untag", img.ID, "")
  1142. }
  1143. }
  1144. if len(srv.runtime.repositories.ByID()[img.ID]) == 0 {
  1145. if err := srv.deleteImageAndChildren(img.ID, &imgs); err != nil {
  1146. if err != ErrImageReferenced {
  1147. return imgs, err
  1148. }
  1149. } else if err := srv.deleteImageParents(img, &imgs); err != nil {
  1150. if err != ErrImageReferenced {
  1151. return imgs, err
  1152. }
  1153. }
  1154. }
  1155. return imgs, nil
  1156. }
  1157. func (srv *Server) ImageDelete(name string, autoPrune bool) ([]APIRmi, error) {
  1158. img, err := srv.runtime.repositories.LookupImage(name)
  1159. if err != nil {
  1160. return nil, fmt.Errorf("No such image: %s", name)
  1161. }
  1162. if !autoPrune {
  1163. if err := srv.runtime.graph.Delete(img.ID); err != nil {
  1164. return nil, fmt.Errorf("Cannot delete image %s: %s", name, err)
  1165. }
  1166. return nil, nil
  1167. }
  1168. // Prevent deletion if image is used by a running container
  1169. for _, container := range srv.runtime.List() {
  1170. if container.State.Running {
  1171. parent, err := srv.runtime.repositories.LookupImage(container.Image)
  1172. if err != nil {
  1173. return nil, err
  1174. }
  1175. if err := parent.WalkHistory(func(p *Image) error {
  1176. if img.ID == p.ID {
  1177. return fmt.Errorf("Conflict, cannot delete %s because the running container %s is using it", name, container.ID)
  1178. }
  1179. return nil
  1180. }); err != nil {
  1181. return nil, err
  1182. }
  1183. }
  1184. }
  1185. if strings.Contains(img.ID, name) {
  1186. //delete via ID
  1187. return srv.deleteImage(img, "", "")
  1188. }
  1189. name, tag := utils.ParseRepositoryTag(name)
  1190. return srv.deleteImage(img, name, tag)
  1191. }
  1192. func (srv *Server) ImageGetCached(imgID string, config *Config) (*Image, error) {
  1193. // Retrieve all images
  1194. images, err := srv.runtime.graph.Map()
  1195. if err != nil {
  1196. return nil, err
  1197. }
  1198. // Store the tree in a map of map (map[parentId][childId])
  1199. imageMap := make(map[string]map[string]struct{})
  1200. for _, img := range images {
  1201. if _, exists := imageMap[img.Parent]; !exists {
  1202. imageMap[img.Parent] = make(map[string]struct{})
  1203. }
  1204. imageMap[img.Parent][img.ID] = struct{}{}
  1205. }
  1206. // Loop on the children of the given image and check the config
  1207. for elem := range imageMap[imgID] {
  1208. img, err := srv.runtime.graph.Get(elem)
  1209. if err != nil {
  1210. return nil, err
  1211. }
  1212. if CompareConfig(&img.ContainerConfig, config) {
  1213. return img, nil
  1214. }
  1215. }
  1216. return nil, nil
  1217. }
  1218. func (srv *Server) RegisterLinks(name string, hostConfig *HostConfig) error {
  1219. runtime := srv.runtime
  1220. container := runtime.Get(name)
  1221. if container == nil {
  1222. return fmt.Errorf("No such container: %s", name)
  1223. }
  1224. if hostConfig != nil && hostConfig.Links != nil {
  1225. for _, l := range hostConfig.Links {
  1226. parts, err := parseLink(l)
  1227. if err != nil {
  1228. return err
  1229. }
  1230. child, err := srv.runtime.GetByName(parts["name"])
  1231. if err != nil {
  1232. return err
  1233. }
  1234. if child == nil {
  1235. return fmt.Errorf("Could not get container for %s", parts["name"])
  1236. }
  1237. if err := runtime.RegisterLink(container, child, parts["alias"]); err != nil {
  1238. return err
  1239. }
  1240. }
  1241. // After we load all the links into the runtime
  1242. // set them to nil on the hostconfig
  1243. hostConfig.Links = nil
  1244. if err := container.writeHostConfig(); err != nil {
  1245. return err
  1246. }
  1247. }
  1248. return nil
  1249. }
  1250. func (srv *Server) ContainerStart(job *engine.Job) string {
  1251. if len(job.Args) < 1 {
  1252. return fmt.Sprintf("Usage: %s container_id", job.Name)
  1253. }
  1254. name := job.Args[0]
  1255. runtime := srv.runtime
  1256. container := runtime.Get(name)
  1257. if container == nil {
  1258. return fmt.Sprintf("No such container: %s", name)
  1259. }
  1260. // If no environment was set, then no hostconfig was passed.
  1261. if len(job.Environ()) > 0 {
  1262. var hostConfig HostConfig
  1263. if err := job.ExportEnv(&hostConfig); err != nil {
  1264. return err.Error()
  1265. }
  1266. // Validate the HostConfig binds. Make sure that:
  1267. // 1) the source of a bind mount isn't /
  1268. // The bind mount "/:/foo" isn't allowed.
  1269. // 2) Check that the source exists
  1270. // The source to be bind mounted must exist.
  1271. for _, bind := range hostConfig.Binds {
  1272. splitBind := strings.Split(bind, ":")
  1273. source := splitBind[0]
  1274. // refuse to bind mount "/" to the container
  1275. if source == "/" {
  1276. return fmt.Sprintf("Invalid bind mount '%s' : source can't be '/'", bind)
  1277. }
  1278. // ensure the source exists on the host
  1279. _, err := os.Stat(source)
  1280. if err != nil && os.IsNotExist(err) {
  1281. return fmt.Sprintf("Invalid bind mount '%s' : source doesn't exist", bind)
  1282. }
  1283. }
  1284. // Register any links from the host config before starting the container
  1285. // FIXME: we could just pass the container here, no need to lookup by name again.
  1286. if err := srv.RegisterLinks(name, &hostConfig); err != nil {
  1287. return err.Error()
  1288. }
  1289. container.hostConfig = &hostConfig
  1290. container.ToDisk()
  1291. }
  1292. if err := container.Start(); err != nil {
  1293. return fmt.Sprintf("Cannot start container %s: %s", name, err)
  1294. }
  1295. srv.LogEvent("start", container.ID, runtime.repositories.ImageName(container.Image))
  1296. return "0"
  1297. }
  1298. func (srv *Server) ContainerStop(name string, t int) error {
  1299. if container := srv.runtime.Get(name); container != nil {
  1300. if err := container.Stop(t); err != nil {
  1301. return fmt.Errorf("Cannot stop container %s: %s", name, err)
  1302. }
  1303. srv.LogEvent("stop", container.ID, srv.runtime.repositories.ImageName(container.Image))
  1304. } else {
  1305. return fmt.Errorf("No such container: %s", name)
  1306. }
  1307. return nil
  1308. }
  1309. func (srv *Server) ContainerWait(name string) (int, error) {
  1310. if container := srv.runtime.Get(name); container != nil {
  1311. return container.Wait(), nil
  1312. }
  1313. return 0, fmt.Errorf("No such container: %s", name)
  1314. }
  1315. func (srv *Server) ContainerResize(name string, h, w int) error {
  1316. if container := srv.runtime.Get(name); container != nil {
  1317. return container.Resize(h, w)
  1318. }
  1319. return fmt.Errorf("No such container: %s", name)
  1320. }
  1321. func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, stderr bool, inStream io.ReadCloser, outStream, errStream io.Writer) error {
  1322. container := srv.runtime.Get(name)
  1323. if container == nil {
  1324. return fmt.Errorf("No such container: %s", name)
  1325. }
  1326. //logs
  1327. if logs {
  1328. cLog, err := container.ReadLog("json")
  1329. if err != nil && os.IsNotExist(err) {
  1330. // Legacy logs
  1331. utils.Errorf("Old logs format")
  1332. if stdout {
  1333. cLog, err := container.ReadLog("stdout")
  1334. if err != nil {
  1335. utils.Errorf("Error reading logs (stdout): %s", err)
  1336. } else if _, err := io.Copy(outStream, cLog); err != nil {
  1337. utils.Errorf("Error streaming logs (stdout): %s", err)
  1338. }
  1339. }
  1340. if stderr {
  1341. cLog, err := container.ReadLog("stderr")
  1342. if err != nil {
  1343. utils.Errorf("Error reading logs (stderr): %s", err)
  1344. } else if _, err := io.Copy(errStream, cLog); err != nil {
  1345. utils.Errorf("Error streaming logs (stderr): %s", err)
  1346. }
  1347. }
  1348. } else if err != nil {
  1349. utils.Errorf("Error reading logs (json): %s", err)
  1350. } else {
  1351. dec := json.NewDecoder(cLog)
  1352. for {
  1353. l := &utils.JSONLog{}
  1354. if err := dec.Decode(l); err == io.EOF {
  1355. break
  1356. } else if err != nil {
  1357. utils.Errorf("Error streaming logs: %s", err)
  1358. break
  1359. }
  1360. if l.Stream == "stdout" && stdout {
  1361. fmt.Fprintf(outStream, "%s", l.Log)
  1362. }
  1363. if l.Stream == "stderr" && stderr {
  1364. fmt.Fprintf(errStream, "%s", l.Log)
  1365. }
  1366. }
  1367. }
  1368. }
  1369. //stream
  1370. if stream {
  1371. if container.State.Ghost {
  1372. return fmt.Errorf("Impossible to attach to a ghost container")
  1373. }
  1374. var (
  1375. cStdin io.ReadCloser
  1376. cStdout, cStderr io.Writer
  1377. cStdinCloser io.Closer
  1378. )
  1379. if stdin {
  1380. r, w := io.Pipe()
  1381. go func() {
  1382. defer w.Close()
  1383. defer utils.Debugf("Closing buffered stdin pipe")
  1384. io.Copy(w, inStream)
  1385. }()
  1386. cStdin = r
  1387. cStdinCloser = inStream
  1388. }
  1389. if stdout {
  1390. cStdout = outStream
  1391. }
  1392. if stderr {
  1393. cStderr = errStream
  1394. }
  1395. <-container.Attach(cStdin, cStdinCloser, cStdout, cStderr)
  1396. // If we are in stdinonce mode, wait for the process to end
  1397. // otherwise, simply return
  1398. if container.Config.StdinOnce && !container.Config.Tty {
  1399. container.Wait()
  1400. }
  1401. }
  1402. return nil
  1403. }
  1404. func (srv *Server) ContainerInspect(name string) (*Container, error) {
  1405. if container := srv.runtime.Get(name); container != nil {
  1406. return container, nil
  1407. }
  1408. return nil, fmt.Errorf("No such container: %s", name)
  1409. }
  1410. func (srv *Server) ImageInspect(name string) (*Image, error) {
  1411. if image, err := srv.runtime.repositories.LookupImage(name); err == nil && image != nil {
  1412. return image, nil
  1413. }
  1414. return nil, fmt.Errorf("No such image: %s", name)
  1415. }
  1416. func (srv *Server) ContainerCopy(name string, resource string, out io.Writer) error {
  1417. if container := srv.runtime.Get(name); container != nil {
  1418. data, err := container.Copy(resource)
  1419. if err != nil {
  1420. return err
  1421. }
  1422. if _, err := io.Copy(out, data); err != nil {
  1423. return err
  1424. }
  1425. return nil
  1426. }
  1427. return fmt.Errorf("No such container: %s", name)
  1428. }
  1429. func NewServer(eng *engine.Engine, config *DaemonConfig) (*Server, error) {
  1430. runtime, err := NewRuntime(config)
  1431. if err != nil {
  1432. return nil, err
  1433. }
  1434. srv := &Server{
  1435. Eng: eng,
  1436. runtime: runtime,
  1437. pullingPool: make(map[string]struct{}),
  1438. pushingPool: make(map[string]struct{}),
  1439. events: make([]utils.JSONMessage, 0, 64), //only keeps the 64 last events
  1440. listeners: make(map[string]chan utils.JSONMessage),
  1441. reqFactory: nil,
  1442. }
  1443. runtime.srv = srv
  1444. return srv, nil
  1445. }
  1446. func (srv *Server) HTTPRequestFactory(metaHeaders map[string][]string) *utils.HTTPRequestFactory {
  1447. if srv.reqFactory == nil {
  1448. ud := utils.NewHTTPUserAgentDecorator(srv.versionInfos()...)
  1449. md := &utils.HTTPMetaHeadersDecorator{
  1450. Headers: metaHeaders,
  1451. }
  1452. factory := utils.NewHTTPRequestFactory(ud, md)
  1453. srv.reqFactory = factory
  1454. }
  1455. return srv.reqFactory
  1456. }
  1457. func (srv *Server) LogEvent(action, id, from string) *utils.JSONMessage {
  1458. now := time.Now().Unix()
  1459. jm := utils.JSONMessage{Status: action, ID: id, From: from, Time: now}
  1460. srv.events = append(srv.events, jm)
  1461. for _, c := range srv.listeners {
  1462. select { // non blocking channel
  1463. case c <- jm:
  1464. default:
  1465. }
  1466. }
  1467. return &jm
  1468. }
  1469. type Server struct {
  1470. sync.Mutex
  1471. runtime *Runtime
  1472. pullingPool map[string]struct{}
  1473. pushingPool map[string]struct{}
  1474. events []utils.JSONMessage
  1475. listeners map[string]chan utils.JSONMessage
  1476. reqFactory *utils.HTTPRequestFactory
  1477. Eng *engine.Engine
  1478. }