store.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. package fs
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "github.com/dotcloud/docker/future"
  6. _ "github.com/mattn/go-sqlite3"
  7. "github.com/shykes/gorp" //Forked to implement CreateTablesOpts
  8. "io"
  9. "io/ioutil"
  10. "os"
  11. "path"
  12. "path/filepath"
  13. "strings"
  14. "syscall"
  15. "time"
  16. )
  17. type Store struct {
  18. Root string
  19. db *sql.DB
  20. orm *gorp.DbMap
  21. layers *LayerStore
  22. }
  23. type Archive io.Reader
  24. func New(root string) (*Store, error) {
  25. isNewStore := true
  26. if err := os.Mkdir(root, 0700); err != nil && !os.IsExist(err) {
  27. return nil, err
  28. }
  29. db, err := sql.Open("sqlite3", path.Join(root, "db"))
  30. if err != nil {
  31. return nil, err
  32. }
  33. orm := &gorp.DbMap{Db: db, Dialect: gorp.SqliteDialect{}}
  34. orm.AddTableWithName(Image{}, "images").SetKeys(false, "Id")
  35. orm.AddTableWithName(Path{}, "paths").SetKeys(false, "Path", "Image")
  36. orm.AddTableWithName(Mountpoint{}, "mountpoints").SetKeys(false, "Root")
  37. orm.AddTableWithName(Tag{}, "tags").SetKeys(false, "TagName")
  38. if isNewStore {
  39. if err := orm.CreateTablesOpts(true); err != nil {
  40. return nil, err
  41. }
  42. }
  43. layers, err := NewLayerStore(path.Join(root, "layers"))
  44. if err != nil {
  45. return nil, err
  46. }
  47. return &Store{
  48. Root: root,
  49. db: db,
  50. orm: orm,
  51. layers: layers,
  52. }, nil
  53. }
  54. func (store *Store) imageList(src []interface{}) []*Image {
  55. var images []*Image
  56. for _, i := range src {
  57. img := i.(*Image)
  58. img.store = store
  59. images = append(images, img)
  60. }
  61. return images
  62. }
  63. func (store *Store) Images() ([]*Image, error) {
  64. images, err := store.orm.Select(Image{}, "select * from images")
  65. if err != nil {
  66. return nil, err
  67. }
  68. return store.imageList(images), nil
  69. }
  70. func (store *Store) Paths() ([]string, error) {
  71. var paths []string
  72. rows, err := store.db.Query("select distinct Path from paths order by Path")
  73. if err != nil {
  74. return nil, err
  75. }
  76. for rows.Next() {
  77. var path string
  78. if err := rows.Scan(&path); err != nil {
  79. return nil, err
  80. }
  81. paths = append(paths, path)
  82. }
  83. return paths, nil
  84. }
  85. func (store *Store) RemoveInPath(pth string) error {
  86. images, err := store.List(pth)
  87. if err != nil {
  88. return err
  89. }
  90. for _, img := range images {
  91. if err = store.Remove(img); err != nil {
  92. return err
  93. }
  94. }
  95. return nil
  96. }
  97. func (store *Store) Remove(img *Image) error {
  98. _, err := store.orm.Delete(img)
  99. return err
  100. }
  101. func (store *Store) List(pth string) ([]*Image, error) {
  102. pth = path.Clean(pth)
  103. images, err := store.orm.Select(Image{}, "select images.* from images, paths where Path=? and paths.Image=images.Id order by images.Created desc", pth)
  104. if err != nil {
  105. return nil, err
  106. }
  107. return store.imageList(images), nil
  108. }
  109. func (store *Store) Find(pth string) (*Image, error) {
  110. pth = path.Clean(pth)
  111. img, err := store.Get(pth)
  112. if err != nil {
  113. return nil, err
  114. } else if img != nil {
  115. return img, nil
  116. }
  117. var q string
  118. var args []interface{}
  119. // FIXME: this breaks if the path contains a ':'
  120. // If format is path:rev
  121. if parts := strings.SplitN(pth, ":", 2); len(parts) == 2 {
  122. q = "select Images.* from images, paths where Path=? and images.Id=? and paths.Image=images.Id"
  123. args = []interface{}{parts[0], parts[1]}
  124. // If format is path:rev
  125. } else {
  126. q = "select images.* from images, paths where Path=? and paths.Image=images.Id order by images.Created desc limit 1"
  127. args = []interface{}{parts[0]}
  128. }
  129. images, err := store.orm.Select(Image{}, q, args...)
  130. if err != nil {
  131. return nil, err
  132. } else if len(images) < 1 {
  133. return nil, nil
  134. }
  135. img = images[0].(*Image)
  136. img.store = store
  137. return img, nil
  138. }
  139. func (store *Store) Get(id string) (*Image, error) {
  140. img, err := store.orm.Get(Image{}, id)
  141. if img == nil {
  142. return nil, err
  143. }
  144. res := img.(*Image)
  145. res.store = store
  146. return res, err
  147. }
  148. func (store *Store) Create(layerData Archive, parent *Image, pth, comment string) (*Image, error) {
  149. // FIXME: actually do something with the layer...
  150. img := &Image{
  151. Id: future.RandomId(),
  152. Comment: comment,
  153. Created: time.Now().Unix(),
  154. store: store,
  155. }
  156. if parent != nil {
  157. img.Parent = parent.Id
  158. }
  159. // FIXME: Archive should contain compression info. For now we only support uncompressed.
  160. err := store.Register(layerData, img, pth)
  161. return img, err
  162. }
  163. func (store *Store) Register(layerData Archive, img *Image, pth string) error {
  164. img.store = store
  165. _, err := store.layers.AddLayer(img.Id, layerData)
  166. if err != nil {
  167. return fmt.Errorf("Could not add layer: %s", err)
  168. }
  169. pathObj := &Path{
  170. Path: path.Clean(pth),
  171. Image: img.Id,
  172. }
  173. trans, err := store.orm.Begin()
  174. if err != nil {
  175. return fmt.Errorf("Could not begin transaction: %s", err)
  176. }
  177. if err := trans.Insert(img); err != nil {
  178. return fmt.Errorf("Could not insert image info: %s", err)
  179. }
  180. if err := trans.Insert(pathObj); err != nil {
  181. return fmt.Errorf("Could not insert path info: %s", err)
  182. }
  183. if err := trans.Commit(); err != nil {
  184. return fmt.Errorf("Could not commit transaction: %s", err)
  185. }
  186. return nil
  187. }
  188. func (store *Store) Layers() []string {
  189. return store.layers.List()
  190. }
  191. type Image struct {
  192. Id string
  193. Parent string
  194. Comment string
  195. Created int64
  196. store *Store `db:"-"`
  197. }
  198. func (image *Image) Copy(pth string) (*Image, error) {
  199. if err := image.store.orm.Insert(&Path{Path: pth, Image: image.Id}); err != nil {
  200. return nil, err
  201. }
  202. return image, nil
  203. }
  204. type Mountpoint struct {
  205. Image string
  206. Root string
  207. Rw string
  208. Store *Store `db:"-"`
  209. }
  210. func (image *Image) Mountpoint(root, rw string) (*Mountpoint, error) {
  211. mountpoint := &Mountpoint{
  212. Root: path.Clean(root),
  213. Rw: path.Clean(rw),
  214. Image: image.Id,
  215. Store: image.store,
  216. }
  217. if err := image.store.orm.Insert(mountpoint); err != nil {
  218. return nil, err
  219. }
  220. return mountpoint, nil
  221. }
  222. func (image *Image) layers() ([]string, error) {
  223. var list []string
  224. var err error
  225. currentImg := image
  226. for currentImg != nil {
  227. if layer := image.store.layers.Get(currentImg.Id); layer != "" {
  228. list = append(list, layer)
  229. } else {
  230. return list, fmt.Errorf("Layer not found for image %s", image.Id)
  231. }
  232. currentImg, err = currentImg.store.Get(currentImg.Parent)
  233. if err != nil {
  234. return list, fmt.Errorf("Error while getting parent image: %v", err)
  235. }
  236. }
  237. if len(list) == 0 {
  238. return nil, fmt.Errorf("No layer found for image %s\n", image.Id)
  239. }
  240. return list, nil
  241. }
  242. func (image *Image) Mountpoints() ([]*Mountpoint, error) {
  243. var mountpoints []*Mountpoint
  244. res, err := image.store.orm.Select(Mountpoint{}, "select * from mountpoints where Image=?", image.Id)
  245. if err != nil {
  246. return nil, err
  247. }
  248. for _, mp := range res {
  249. mountpoints = append(mountpoints, mp.(*Mountpoint))
  250. }
  251. return mountpoints, nil
  252. }
  253. func (image *Image) Mount(root, rw string) (*Mountpoint, error) {
  254. var mountpoint *Mountpoint
  255. if mp, err := image.store.FetchMountpoint(root, rw); err != nil {
  256. return nil, err
  257. } else if mp == nil {
  258. mountpoint, err = image.Mountpoint(root, rw)
  259. if err != nil {
  260. return nil, fmt.Errorf("Could not create mountpoint: %s", err)
  261. } else if mountpoint == nil {
  262. return nil, fmt.Errorf("No mountpoint created")
  263. }
  264. } else {
  265. mountpoint = mp
  266. }
  267. if err := mountpoint.createFolders(); err != nil {
  268. return nil, err
  269. }
  270. // FIXME: Now mount the layers
  271. rwBranch := fmt.Sprintf("%v=rw", mountpoint.Rw)
  272. roBranches := ""
  273. layers, err := image.layers()
  274. if err != nil {
  275. return nil, err
  276. }
  277. for _, layer := range layers {
  278. roBranches += fmt.Sprintf("%v=ro:", layer)
  279. }
  280. branches := fmt.Sprintf("br:%v:%v", rwBranch, roBranches)
  281. if err := mount("none", mountpoint.Root, "aufs", 0, branches); err != nil {
  282. return mountpoint, err
  283. }
  284. if !mountpoint.Mounted() {
  285. return mountpoint, fmt.Errorf("Mount failed")
  286. }
  287. // FIXME: Create tests for deletion
  288. // FIXME: move this part to change.go, maybe refactor
  289. // fs.Change() to avoid the fake mountpoint
  290. // Retrieve the changeset from the parent and apply it to the container
  291. // - Retrieve the changes
  292. changes, err := image.store.Changes(&Mountpoint{
  293. Image: image.Id,
  294. Root: layers[0],
  295. Rw: layers[0],
  296. Store: image.store})
  297. if err != nil {
  298. return nil, err
  299. }
  300. // Iterate on changes
  301. for _, c := range changes {
  302. // If there is a delete
  303. if c.Kind == ChangeDelete {
  304. // Make sure the directory exists
  305. file_path, file_name := path.Dir(c.Path), path.Base(c.Path)
  306. if err := os.MkdirAll(path.Join(mountpoint.Rw, file_path), 0755); err != nil {
  307. return nil, err
  308. }
  309. // And create the whiteout (we just need to create empty file, discard the return)
  310. if _, err := os.Create(path.Join(path.Join(mountpoint.Rw, file_path),
  311. ".wh."+path.Base(file_name))); err != nil {
  312. return nil, err
  313. }
  314. }
  315. }
  316. return mountpoint, nil
  317. }
  318. func (mp *Mountpoint) EnsureMounted() error {
  319. if mp.Mounted() {
  320. return nil
  321. }
  322. img, err := mp.Store.Get(mp.Image)
  323. if err != nil {
  324. return err
  325. }
  326. _, err = img.Mount(mp.Root, mp.Rw)
  327. return err
  328. }
  329. func (mp *Mountpoint) createFolders() error {
  330. if err := os.Mkdir(mp.Root, 0755); err != nil && !os.IsExist(err) {
  331. return err
  332. }
  333. if err := os.Mkdir(mp.Rw, 0755); err != nil && !os.IsExist(err) {
  334. return err
  335. }
  336. return nil
  337. }
  338. func (mp *Mountpoint) Mounted() bool {
  339. root, err := os.Stat(mp.Root)
  340. if err != nil {
  341. if os.IsNotExist(err) {
  342. return false
  343. }
  344. panic(err)
  345. }
  346. parent, err := os.Stat(filepath.Join(mp.Root, ".."))
  347. if err != nil {
  348. panic(err)
  349. }
  350. rootSt := root.Sys().(*syscall.Stat_t)
  351. parentSt := parent.Sys().(*syscall.Stat_t)
  352. return rootSt.Dev != parentSt.Dev
  353. }
  354. func (mp *Mountpoint) Umount() error {
  355. if !mp.Mounted() {
  356. return fmt.Errorf("Mountpoint doesn't seem to be mounted")
  357. }
  358. if err := syscall.Unmount(mp.Root, 0); err != nil {
  359. return fmt.Errorf("Unmount syscall failed: %v", err)
  360. }
  361. if mp.Mounted() {
  362. return fmt.Errorf("Umount: Filesystem still mounted after calling umount(%v)", mp.Root)
  363. }
  364. // Even though we just unmounted the filesystem, AUFS will prevent deleting the mntpoint
  365. // for some time. We'll just keep retrying until it succeeds.
  366. for retries := 0; retries < 1000; retries++ {
  367. err := os.Remove(mp.Root)
  368. if err == nil {
  369. // rm mntpoint succeeded
  370. return nil
  371. }
  372. if os.IsNotExist(err) {
  373. // mntpoint doesn't exist anymore. Success.
  374. return nil
  375. }
  376. // fmt.Printf("(%v) Remove %v returned: %v\n", retries, mp.Root, err)
  377. time.Sleep(10 * time.Millisecond)
  378. }
  379. return fmt.Errorf("Umount: Failed to umount %v", mp.Root)
  380. }
  381. func (mp *Mountpoint) Deregister() error {
  382. if mp.Mounted() {
  383. return fmt.Errorf("Mountpoint is currently mounted, can't deregister")
  384. }
  385. _, err := mp.Store.orm.Delete(mp)
  386. return err
  387. }
  388. func (store *Store) FetchMountpoint(root, rw string) (*Mountpoint, error) {
  389. res, err := store.orm.Select(Mountpoint{}, "select * from mountpoints where Root=? and Rw=?", root, rw)
  390. if err != nil {
  391. return nil, err
  392. } else if len(res) < 1 || res[0] == nil {
  393. return nil, nil
  394. }
  395. mp := res[0].(*Mountpoint)
  396. mp.Store = store
  397. return mp, nil
  398. }
  399. // OpenFile opens the named file for reading.
  400. func (mp *Mountpoint) OpenFile(path string, flag int, perm os.FileMode) (*os.File, error) {
  401. if err := mp.EnsureMounted(); err != nil {
  402. return nil, err
  403. }
  404. return os.OpenFile(filepath.Join(mp.Root, path), flag, perm)
  405. }
  406. // ReadDir reads the directory named by dirname, relative to the Mountpoint's root,
  407. // and returns a list of sorted directory entries
  408. func (mp *Mountpoint) ReadDir(dirname string) ([]os.FileInfo, error) {
  409. if err := mp.EnsureMounted(); err != nil {
  410. return nil, err
  411. }
  412. return ioutil.ReadDir(filepath.Join(mp.Root, dirname))
  413. }
  414. func (store *Store) AddTag(imageId, tagName string) error {
  415. if image, err := store.Get(imageId); err != nil {
  416. return err
  417. } else if image == nil {
  418. return fmt.Errorf("No image with ID %s", imageId)
  419. }
  420. err2 := store.orm.Insert(&Tag{
  421. TagName: tagName,
  422. Image: imageId,
  423. })
  424. return err2
  425. }
  426. func (store *Store) GetByTag(tagName string) (*Image, error) {
  427. res, err := store.orm.Get(Tag{}, tagName)
  428. if err != nil {
  429. return nil, err
  430. } else if res == nil {
  431. return nil, fmt.Errorf("No image associated to tag \"%s\"", tagName)
  432. }
  433. tag := res.(*Tag)
  434. img, err2 := store.Get(tag.Image)
  435. if err2 != nil {
  436. return nil, err2
  437. } else if img == nil {
  438. return nil, fmt.Errorf("Tag was found but image seems to be inexistent.")
  439. }
  440. return img, nil
  441. }
  442. type Path struct {
  443. Path string
  444. Image string
  445. }
  446. type Tag struct {
  447. TagName string
  448. Image string
  449. }