[ARVADOS] created: 2.1.0-920-g3d8ed2b76
Git user
git at public.arvados.org
Mon Jun 14 14:15:37 UTC 2021
at 3d8ed2b76b87033b4fed70e6b0998694c4326b8c (commit)
commit 3d8ed2b76b87033b4fed70e6b0998694c4326b8c
Author: Tom Clegg <tom at curii.com>
Date: Mon Jun 14 09:22:32 2021 -0400
17805: Access containers and container requests via sitefs (WIP).
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom at curii.com>
diff --git a/lib/mount/fs.go b/lib/mount/fs.go
index c008b96af..5d8b38688 100644
--- a/lib/mount/fs.go
+++ b/lib/mount/fs.go
@@ -271,6 +271,8 @@ func (fs *keepFS) fillStat(stat *fuse.Stat_t, fi os.FileInfo) {
var m uint32
if fi.IsDir() {
m = m | fuse.S_IFDIR
+ } else if fi.Mode()&os.ModeSymlink != 0 {
+ m = m | fuse.S_IFLNK
} else {
m = m | fuse.S_IFREG
}
@@ -315,6 +317,15 @@ func (fs *keepFS) Write(path string, buf []byte, ofst int64, fh uint64) (n int)
return n
}
+func (fs *keepFS) Readlink(path string) (n int, target string) {
+ defer fs.debugPanics()
+ if target, err := fs.root.Readlink(path); err != nil {
+ return fs.errCode(err), ""
+ } else {
+ return 0, target
+ }
+}
+
func (fs *keepFS) Read(path string, buf []byte, ofst int64, fh uint64) (n int) {
defer fs.debugPanics()
f := fs.lookupFH(fh)
diff --git a/sdk/go/arvados/container.go b/sdk/go/arvados/container.go
index f54263470..72acd63de 100644
--- a/sdk/go/arvados/container.go
+++ b/sdk/go/arvados/container.go
@@ -20,6 +20,7 @@ type Container struct {
Environment map[string]string `json:"environment"`
LockedByUUID string `json:"locked_by_uuid"`
Mounts map[string]Mount `json:"mounts"`
+ Log string `json:"log"`
Output string `json:"output"`
OutputPath string `json:"output_path"`
Priority int64 `json:"priority"`
diff --git a/sdk/go/arvados/fs_base.go b/sdk/go/arvados/fs_base.go
index 2478641df..d2de43819 100644
--- a/sdk/go/arvados/fs_base.go
+++ b/sdk/go/arvados/fs_base.go
@@ -93,6 +93,7 @@ type FileSystem interface {
Remove(name string) error
RemoveAll(name string) error
Rename(oldname, newname string) error
+ Readlink(name string) (string, error)
// Write buffered data from memory to storage, returning when
// all updates have been saved to persistent storage.
@@ -483,6 +484,21 @@ func (fs *fileSystem) Stat(name string) (os.FileInfo, error) {
return node.FileInfo(), nil
}
+func (fs *fileSystem) Readlink(name string) (string, error) {
+ node, err := rlookup(fs.root, name)
+ if err != nil {
+ return "", err
+ }
+ if node.FileInfo().Mode()&os.ModeSymlink == 0 {
+ return "", ErrInvalidArgument
+ }
+ buf := make([]byte, int(node.FileInfo().Size()))
+ // FIXME: target/size could change here between calls to
+ // Size() and Read(), causing incorrect output
+ _, _, err = node.Read(buf, filenodePtr{})
+ return string(buf), err
+}
+
func (fs *fileSystem) Rename(oldname, newname string) error {
olddir, oldname := path.Split(oldname)
if oldname == "" || oldname == "." || oldname == ".." {
diff --git a/sdk/go/arvados/fs_getternode.go b/sdk/go/arvados/fs_getternode.go
index 966fe9d5c..f28c5744b 100644
--- a/sdk/go/arvados/fs_getternode.go
+++ b/sdk/go/arvados/fs_getternode.go
@@ -51,8 +51,9 @@ func (gn *getternode) FileInfo() os.FileInfo {
size = gn.data.Size()
}
return fileinfo{
+ name: gn.treenode.fileinfo.name,
modTime: time.Now(),
- mode: 0444,
+ mode: 0444 | gn.treenode.fileinfo.mode,
size: size,
}
}
diff --git a/sdk/go/arvados/fs_lookup.go b/sdk/go/arvados/fs_lookup.go
index 021e8241c..bd9d70c5f 100644
--- a/sdk/go/arvados/fs_lookup.go
+++ b/sdk/go/arvados/fs_lookup.go
@@ -45,29 +45,37 @@ func (ln *lookupnode) Readdir() ([]os.FileInfo, error) {
defer ln.staleLock.Unlock()
checkTime := time.Now()
if ln.stale(ln.staleAll) {
- all, err := ln.loadAll(ln)
+ ln.treenode.Lock()
+ err := ln.refreshAll(checkTime)
+ ln.treenode.Unlock()
if err != nil {
return nil, err
}
- for _, child := range all {
- ln.treenode.Lock()
- _, err = ln.treenode.Child(child.FileInfo().Name(), func(inode) (inode, error) {
- return child, nil
- })
- ln.treenode.Unlock()
- if err != nil {
- return nil, err
- }
- }
- ln.staleAll = checkTime
- // No value in ln.staleOne can make a difference to an
- // "entry is stale?" test now, because no value is
- // newer than ln.staleAll. Reclaim memory.
- ln.staleOne = nil
}
return ln.treenode.Readdir()
}
+func (ln *lookupnode) refreshAll(checkTime time.Time) error {
+ all, err := ln.loadAll(ln)
+ if err != nil {
+ return err
+ }
+ for _, child := range all {
+ _, err = ln.treenode.Child(child.FileInfo().Name(), func(inode) (inode, error) {
+ return child, nil
+ })
+ if err != nil {
+ return err
+ }
+ }
+ ln.staleAll = checkTime
+ // No value in ln.staleOne can make a difference to an
+ // "entry is stale?" test now, because no value is
+ // newer than ln.staleAll. Reclaim memory.
+ ln.staleOne = nil
+ return nil
+}
+
// Child rejects (with ErrInvalidArgument) calls to add/replace
// children, instead calling loadOne when a non-existing child is
// looked up.
@@ -79,6 +87,10 @@ func (ln *lookupnode) Child(name string, replace func(inode) (inode, error)) (in
var err error
if ln.stale(ln.staleAll) && ln.stale(ln.staleOne[name]) {
existing, err = ln.treenode.Child(name, func(inode) (inode, error) {
+ if ln.loadOne == nil {
+ err = ln.refreshAll(checkTime)
+ return ln.treenode.inodes[name], err
+ }
return ln.loadOne(ln, name)
})
if err == nil && existing != nil {
diff --git a/sdk/go/arvados/fs_site.go b/sdk/go/arvados/fs_site.go
index 900893aa3..c68273741 100644
--- a/sdk/go/arvados/fs_site.go
+++ b/sdk/go/arvados/fs_site.go
@@ -5,6 +5,8 @@
package arvados
import (
+ "encoding/json"
+ "fmt"
"os"
"strings"
"sync"
@@ -135,6 +137,10 @@ func (fs *customFileSystem) mountByID(parent inode, id string) inode {
return fs.mountCollection(parent, id)
} else if strings.Contains(id, "-j7d0g-") {
return fs.newProjectNode(fs.root, id, id)
+ } else if strings.Contains(id, "-dz642-") {
+ return fs.mountContainer(fs.root, id)
+ } else if strings.Contains(id, "-xvhdp-") {
+ return fs.mountContainerRequest(fs.root, id)
} else {
return nil
}
@@ -155,6 +161,92 @@ func (fs *customFileSystem) mountCollection(parent inode, id string) inode {
return cfs
}
+func (fs *customFileSystem) mountContainerRequest(parent inode, id string) inode {
+ return &lookupnode{
+ stale: fs.Stale,
+ loadAll: func(parent inode) ([]inode, error) {
+ var all []inode
+ var cr ContainerRequest
+ err := fs.RequestAndDecode(&cr, "GET", "arvados/v1/container_requests/"+id, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ jsondata, _ := json.MarshalIndent(cr, "", " ")
+ jsondata = append(jsondata, '\n')
+ if cr.LogUUID != "" {
+ all = append(all, &getternode{Getter: func() ([]byte, error) { return []byte("../" + cr.LogUUID), nil }, treenode: treenode{fileinfo: fileinfo{name: "log", mode: os.ModeSymlink}}})
+ }
+ if cr.OutputUUID != "" {
+ all = append(all, &getternode{Getter: func() ([]byte, error) { return []byte("../" + cr.OutputUUID), nil }, treenode: treenode{fileinfo: fileinfo{name: "output", mode: os.ModeSymlink}}})
+ }
+ all = append(all,
+ &getternode{Getter: func() ([]byte, error) { return jsondata, nil }, treenode: treenode{fileinfo: fileinfo{name: "json"}}},
+ &getternode{Getter: func() ([]byte, error) { return []byte(cr.UUID + "\n"), nil }, treenode: treenode{fileinfo: fileinfo{name: "uuid"}}},
+ &getternode{Getter: func() ([]byte, error) { return []byte(cr.State + "\n"), nil }, treenode: treenode{fileinfo: fileinfo{name: "state"}}},
+ &getternode{Getter: func() ([]byte, error) { return []byte(cr.ContainerImage + "\n"), nil }, treenode: treenode{fileinfo: fileinfo{name: "container_image"}}},
+ &getternode{Getter: func() ([]byte, error) { return []byte("../" + cr.ContainerUUID), nil }, treenode: treenode{fileinfo: fileinfo{name: "container", mode: os.ModeSymlink}}},
+ )
+ if cr.RequestingContainerUUID != "" {
+ all = append(all, &getternode{Getter: func() ([]byte, error) { return []byte("../" + cr.RequestingContainerUUID), nil }, treenode: treenode{fileinfo: fileinfo{name: "requesting_container", mode: os.ModeSymlink}}})
+ }
+ return all, nil
+ },
+ treenode: treenode{
+ fs: fs,
+ parent: parent,
+ inodes: make(map[string]inode),
+ fileinfo: fileinfo{
+ name: id,
+ modTime: time.Now(),
+ mode: 0755 | os.ModeDir,
+ },
+ },
+ }
+}
+
+func (fs *customFileSystem) mountContainer(parent inode, id string) inode {
+ node := &lookupnode{
+ stale: fs.Stale,
+ loadAll: func(parent inode) ([]inode, error) {
+ var all []inode
+ var c Container
+ err := fs.RequestAndDecode(&c, "GET", "arvados/v1/containers/"+id, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ jsondata, _ := json.MarshalIndent(c, "", " ")
+ jsondata = append(jsondata, '\n')
+ if c.Log != "" {
+ all = append(all, &getternode{Getter: func() ([]byte, error) { return []byte("../" + c.Log), nil }, treenode: treenode{fileinfo: fileinfo{name: "log", mode: os.ModeSymlink}}})
+ }
+ if c.Output != "" {
+ all = append(all, &getternode{Getter: func() ([]byte, error) { return []byte("../" + c.Output), nil }, treenode: treenode{fileinfo: fileinfo{name: "output", mode: os.ModeSymlink}}})
+ }
+ all = append(all,
+ &getternode{Getter: func() ([]byte, error) { return jsondata, nil }, treenode: treenode{fileinfo: fileinfo{name: "json"}}},
+ &getternode{Getter: func() ([]byte, error) { return []byte(c.UUID + "\n"), nil }, treenode: treenode{fileinfo: fileinfo{name: "uuid"}}},
+ &getternode{Getter: func() ([]byte, error) { return []byte(c.State + "\n"), nil }, treenode: treenode{fileinfo: fileinfo{name: "state"}}},
+ &getternode{Getter: func() ([]byte, error) { return []byte("../" + c.ContainerImage), nil }, treenode: treenode{fileinfo: fileinfo{name: "container_image", mode: os.ModeSymlink}}},
+ &getternode{Getter: func() ([]byte, error) { return []byte(c.GatewayAddress + "\n"), nil }, treenode: treenode{fileinfo: fileinfo{name: "gateway_address"}}},
+ &getternode{Getter: func() ([]byte, error) { return []byte(fmt.Sprintf("%d\n", c.ExitCode)), nil }, treenode: treenode{fileinfo: fileinfo{name: "exit_code"}}},
+ &getternode{Getter: func() ([]byte, error) { return []byte(fmt.Sprintf("%v\n", c.InteractiveSessionStarted)), nil }, treenode: treenode{fileinfo: fileinfo{name: "interactive_session_started"}}},
+ )
+ return all, nil
+ },
+ treenode: treenode{
+ fs: fs,
+ parent: parent,
+ inodes: make(map[string]inode),
+ fileinfo: fileinfo{
+ name: id,
+ modTime: time.Now(),
+ mode: 0755 | os.ModeDir,
+ },
+ },
+ }
+ return node
+}
+
func (fs *customFileSystem) newProjectNode(root inode, name, uuid string) inode {
return &lookupnode{
stale: fs.Stale,
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list