This is an automated email from the ASF dual-hosted git repository.

dimuthuupe pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata.git

commit 6c4fdcde76001d3c964a24acc434fc2b0f917600
Author: Yasith Jayawardana <[email protected]>
AuthorDate: Fri Jul 19 03:44:09 2024 -0400

    add airavata-fuse starter implementation
---
 modules/agent-framework/airavata-fuse/.gitignore   |    3 +
 modules/agent-framework/airavata-fuse/Makefile     |   25 +
 modules/agent-framework/airavata-fuse/README.md    |    6 +
 .../agent-framework/airavata-fuse/data/foo/bar.txt |    1 +
 .../agent-framework/airavata-fuse/data/hello.txt   |    1 +
 .../airavata-fuse/src/grpcfs/adapters.go           |   62 +
 .../agent-framework/airavata-fuse/src/grpcfs/fs.go |  232 ++
 .../airavata-fuse/src/grpcfs/go.mod                |   16 +
 .../airavata-fuse/src/grpcfs/go.sum                |   18 +
 .../airavata-fuse/src/grpcfs/grpc.go               |  112 +
 .../airavata-fuse/src/grpcfs/inode.go              |  149 ++
 .../airavata-fuse/src/grpcfs/pb/grpcfs.pb.go       | 2253 ++++++++++++++++++++
 .../airavata-fuse/src/grpcfs/pb/grpcfs_grpc.pb.go  |  380 ++++
 .../airavata-fuse/src/grpcfs_client/go.mod         |   19 +
 .../airavata-fuse/src/grpcfs_client/go.sum         |   18 +
 .../airavata-fuse/src/grpcfs_client/main.go        |   65 +
 .../airavata-fuse/src/grpcfs_server/go.mod         |   18 +
 .../airavata-fuse/src/grpcfs_server/go.sum         |   14 +
 .../airavata-fuse/src/grpcfs_server/main.go        |  222 ++
 .../airavata-fuse/src/proto/grpcfs.proto           |  120 ++
 20 files changed, 3734 insertions(+)

diff --git a/modules/agent-framework/airavata-fuse/.gitignore 
b/modules/agent-framework/airavata-fuse/.gitignore
new file mode 100644
index 0000000000..b121a97be7
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/.gitignore
@@ -0,0 +1,3 @@
+.DS_Store
+bin/
+tmp/
\ No newline at end of file
diff --git a/modules/agent-framework/airavata-fuse/Makefile 
b/modules/agent-framework/airavata-fuse/Makefile
new file mode 100644
index 0000000000..8b81a0a91d
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/Makefile
@@ -0,0 +1,25 @@
+all: init client server
+
+init:
+       rm -rf ./bin && mkdir ./bin
+
+protoc: protoc_init protoc_run
+
+protoc_init:
+       go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest; \
+       go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
+
+protoc_run:
+       cd src && protoc --go_out=. --go-grpc_out=. proto/*.proto
+
+client:
+       cd src/grpcfs_client && go mod tidy && go build -o ../../bin .
+
+server:
+       cd src/grpcfs_server && go mod tidy && go build -o ../../bin .
+
+run_server:
+       bin/server
+
+run_client:
+       bin/client -mount $$PWD/tmp -serve $$PWD/data
\ No newline at end of file
diff --git a/modules/agent-framework/airavata-fuse/README.md 
b/modules/agent-framework/airavata-fuse/README.md
new file mode 100644
index 0000000000..dfc72aa95c
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/README.md
@@ -0,0 +1,6 @@
+# FUSE Client/Server for Airavata
+
+```sh
+make
+```
+Upon running `make`, two binaries (`bin/server` and `bin/client`) will be 
created in the `bin/` folder
\ No newline at end of file
diff --git a/modules/agent-framework/airavata-fuse/data/foo/bar.txt 
b/modules/agent-framework/airavata-fuse/data/foo/bar.txt
new file mode 100644
index 0000000000..c8f9fc8661
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/data/foo/bar.txt
@@ -0,0 +1 @@
+test file - bar.txt
\ No newline at end of file
diff --git a/modules/agent-framework/airavata-fuse/data/hello.txt 
b/modules/agent-framework/airavata-fuse/data/hello.txt
new file mode 100644
index 0000000000..bc7774a7b1
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/data/hello.txt
@@ -0,0 +1 @@
+hello world!
\ No newline at end of file
diff --git a/modules/agent-framework/airavata-fuse/src/grpcfs/adapters.go 
b/modules/agent-framework/airavata-fuse/src/grpcfs/adapters.go
new file mode 100644
index 0000000000..aee9bdf6af
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs/adapters.go
@@ -0,0 +1,62 @@
+package grpcfs
+
+import (
+       pb "grpcfs/pb"
+       "io/fs"
+       "time"
+)
+
+type FileInfoBridge struct {
+       info pb.FileInfo
+}
+
+func (b *FileInfoBridge) Name() string {
+       return b.info.Name
+}
+
+func (b *FileInfoBridge) Size() int64 {
+       return b.info.Size
+}
+
+func (b *FileInfoBridge) Mode() fs.FileMode {
+       return fs.FileMode(b.info.Mode)
+}
+
+func (b *FileInfoBridge) ModTime() time.Time {
+       return b.info.ModTime.AsTime()
+}
+
+func (b *FileInfoBridge) IsDir() bool {
+       return b.info.IsDir
+}
+
+type Sys struct {
+       Ino uint64
+}
+
+func (b *FileInfoBridge) Sys() any {
+       return &Sys{
+               Ino: b.info.Ino,
+       }
+}
+
+type DirEntryBridge struct {
+       info pb.DirEntry
+}
+
+func (b *DirEntryBridge) Name() string {
+       return b.info.Name
+}
+
+func (b *DirEntryBridge) IsDir() bool {
+       return b.info.IsDir
+}
+
+func (b *DirEntryBridge) Type() fs.FileMode {
+       return fs.FileMode(b.info.FileMode)
+}
+
+func (b *DirEntryBridge) Info() (fs.FileInfo, error) {
+       info := &FileInfoBridge{info: *b.info.Info}
+       return info, nil
+}
diff --git a/modules/agent-framework/airavata-fuse/src/grpcfs/fs.go 
b/modules/agent-framework/airavata-fuse/src/grpcfs/fs.go
new file mode 100644
index 0000000000..aec2ab102b
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs/fs.go
@@ -0,0 +1,232 @@
+// place for fuse definitions
+
+package grpcfs
+
+import (
+       "context"
+       "log"
+       "os"
+       "sync"
+
+       pb "grpcfs/pb"
+
+       "github.com/jacobsa/fuse"
+       "github.com/jacobsa/fuse/fuseops"
+       "github.com/jacobsa/fuse/fuseutil"
+       "google.golang.org/grpc"
+       "google.golang.org/grpc/credentials/insecure"
+)
+
+type grpcFs struct {
+       fuseutil.NotImplementedFileSystem
+       root   string
+       inodes *sync.Map
+       logger *log.Logger
+       client pb.FuseServiceClient
+}
+
+var _ fuseutil.FileSystem = &grpcFs{}
+
+// Create a file system that mirrors an existing physical path, in a readonly 
mode
+func FuseServer(
+       grpcHost string,
+       root string,
+       logger *log.Logger) (server fuse.Server, err error) {
+
+       creds := insecure.NewCredentials()
+       conn, err := grpc.NewClient(grpcHost, 
grpc.WithTransportCredentials(creds))
+       if err != nil {
+               return nil, err
+       }
+       client := pb.NewFuseServiceClient(conn)
+
+       if _, err = getStat(client, context.TODO(), root); err != nil {
+               logger.Print("error in getStat() for FS root", err)
+               return nil, err
+       }
+
+       inodes := &sync.Map{}
+       rootInode := &inodeEntry{
+               id:     fuseops.RootInodeID,
+               path:   root,
+               client: client,
+       }
+       inodes.Store(rootInode.Id(), rootInode)
+       server = fuseutil.NewFileSystemServer(&grpcFs{
+               root:   root,
+               inodes: inodes,
+               logger: logger,
+               client: client,
+       })
+       return
+}
+
+func (fs *grpcFs) StatFS(
+       ctx context.Context,
+       op *fuseops.StatFSOp) error {
+
+       res, err := getStatFs(fs.client, ctx, fs.root)
+       if err != nil {
+               return err
+       }
+       op.BlockSize = res.BlockSize
+       op.Blocks = res.Blocks
+       op.BlocksAvailable = res.BlocksAvailable
+       op.BlocksFree = res.BlocksFree
+       op.Inodes = res.Inodes
+       op.InodesFree = res.InodesFree
+       op.IoSize = res.IoSize
+       return nil
+}
+
+func (fs *grpcFs) LookUpInode(
+       ctx context.Context,
+       op *fuseops.LookUpInodeOp) error {
+       fs.logger.Print("fs.LookUpInode - called. ", op)
+       entry, err := getOrCreateInode(fs.inodes, fs.client, ctx, op.Parent, 
op.Name)
+       if err == nil && entry == nil {
+               fs.logger.Print("fs.LookUpInode - file does not exist. ", 
op.Name)
+               return fuse.ENOENT
+       }
+       if err != nil {
+               fs.logger.Printf("fs.LookUpInode - '%v' on '%v': %v", entry, 
op.Name, err)
+               return fuse.EIO
+       }
+       outputEntry := &op.Entry
+       outputEntry.Child = entry.Id()
+       attributes, err := entry.Attributes()
+       if err != nil {
+               fs.logger.Printf("fs.LookUpInode.Attributes for '%v' on '%v': 
%v", entry, op.Name, err)
+               return fuse.EIO
+       }
+       outputEntry.Attributes = *attributes
+       return nil
+}
+
+func (fs *grpcFs) GetInodeAttributes(
+       ctx context.Context,
+       op *fuseops.GetInodeAttributesOp) error {
+       var entry, found = fs.inodes.Load(op.Inode)
+       if !found {
+               return fuse.ENOENT
+       }
+       attributes, err := entry.(Inode).Attributes()
+       if err != nil {
+               fs.logger.Printf("fs.GetInodeAttributes for '%v': %v", entry, 
err)
+               return fuse.EIO
+       }
+       op.Attributes = *attributes
+       return nil
+}
+
+func (fs *grpcFs) OpenDir(
+       ctx context.Context,
+       op *fuseops.OpenDirOp) error {
+       // Allow opening any directory.
+       return nil
+}
+
+func (fs *grpcFs) ReadDir(
+       ctx context.Context,
+       op *fuseops.ReadDirOp) error {
+       log.Print("fs.ReadDir - called. ", op.Inode)
+       var entry, found = fs.inodes.Load(op.Inode)
+       if !found {
+               log.Print("fs.ReadDir - requested dir not found. ", op.Inode)
+               return fuse.ENOENT
+       }
+       log.Print("fs.ReadDir - found requested dir. ", entry)
+       children, err := entry.(Inode).ListChildren(fs.inodes)
+       log.Print("fs.ReadDir - requested children. ", entry)
+       if err != nil {
+               fs.logger.Printf("fs.ReadDir - ListChildren of '%v' failed: 
%v", entry, err)
+               return fuse.EIO
+       }
+       fs.logger.Printf("fs.ReadDir - Got children of '%v': %v", entry, 
children)
+       if op.Offset > fuseops.DirOffset(len(children)) {
+               return nil
+       }
+
+       children = children[op.Offset:]
+
+       for _, child := range children {
+               bytesWritten := fuseutil.WriteDirent(op.Dst[op.BytesRead:], 
*child)
+               if bytesWritten == 0 {
+                       break
+               }
+               op.BytesRead += bytesWritten
+       }
+       return nil
+}
+
+func (fs *grpcFs) OpenFile(
+       ctx context.Context,
+       op *fuseops.OpenFileOp) error {
+
+       var _, found = fs.inodes.Load(op.Inode)
+       if !found {
+               return fuse.ENOENT
+       }
+       return nil
+
+}
+
+func (fs *grpcFs) ReadFile(
+       ctx context.Context,
+       op *fuseops.ReadFileOp) error {
+       var entry, found = fs.inodes.Load(op.Inode)
+       if !found {
+               return fuse.ENOENT
+       }
+       contents, err := entry.(Inode).Contents()
+       if err != nil {
+               fs.logger.Printf("fs.ReadFile - failed for '%v': %v", entry, 
err)
+               return fuse.EIO
+       }
+
+       if op.Offset > int64(len(contents)) {
+               return fuse.EIO
+       }
+
+       contents = contents[op.Offset:]
+       op.BytesRead = copy(op.Dst, contents)
+       return nil
+}
+
+func (fs *grpcFs) WriteFile(
+       ctx context.Context,
+       op *fuseops.WriteFileOp) error {
+       var entry, found = fs.inodes.Load(op.Inode)
+       if !found {
+               return fuse.ENOENT
+       }
+       path := entry.(Inode).Path()
+       fs.logger.Print("fs.WriteFile - called for", path)
+       res, err := writeFile(fs.client, ctx, path, op.Data, op.Offset)
+       if !res || (err != nil) {
+               fs.logger.Printf("fs.WriteFile - failed for '%v': %v", entry, 
err)
+               return fuse.EIO
+       }
+       return nil
+}
+
+func (fs *grpcFs) SetInodeAttributes(
+       ctx context.Context,
+       op *fuseops.SetInodeAttributesOp) error {
+       var entry, found = fs.inodes.Load(op.Inode)
+       if !found {
+               return fuse.ENOENT
+       }
+       path := entry.(Inode).Path()
+       fs.logger.Print("fs.SetInodeAttributes - called for ", path)
+       res, err := setInodeAttributes(fs.client, ctx, path, op.Size, 
(*uint32)(op.Mode), op.Atime, op.Mtime)
+       if (res == nil) || (err != nil) {
+               fs.logger.Printf("fs.SetInodeAttributes - failed for '%v': %v", 
entry, err)
+               return fuse.EIO
+       }
+       op.Attributes.Size = res.Size
+       op.Attributes.Mode = os.FileMode(res.FileMode)
+       op.Attributes.Atime = res.Atime.AsTime()
+       op.Attributes.Mtime = res.Mtime.AsTime()
+       return nil
+}
diff --git a/modules/agent-framework/airavata-fuse/src/grpcfs/go.mod 
b/modules/agent-framework/airavata-fuse/src/grpcfs/go.mod
new file mode 100644
index 0000000000..5a8a3e5351
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs/go.mod
@@ -0,0 +1,16 @@
+module grpcfs
+
+go 1.22.5
+
+require (
+       github.com/jacobsa/fuse v0.0.0-20240626143436-8a36813dc074
+       google.golang.org/grpc v1.65.0
+       google.golang.org/protobuf v1.34.2
+)
+
+require (
+       golang.org/x/net v0.25.0 // indirect
+       golang.org/x/sys v0.20.0 // indirect
+       golang.org/x/text v0.15.0 // indirect
+       google.golang.org/genproto/googleapis/rpc 
v0.0.0-20240528184218-531527333157 // indirect
+)
diff --git a/modules/agent-framework/airavata-fuse/src/grpcfs/go.sum 
b/modules/agent-framework/airavata-fuse/src/grpcfs/go.sum
new file mode 100644
index 0000000000..e35f80a46e
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs/go.sum
@@ -0,0 +1,18 @@
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod 
h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/jacobsa/fuse v0.0.0-20240626143436-8a36813dc074 
h1:rrmTkL654m7vQTYzi9NpEzAO7t0to5f1/jgkvSorVs8=
+github.com/jacobsa/fuse v0.0.0-20240626143436-8a36813dc074/go.mod 
h1:JYi9iIxdYNgxmMgLwtSHO/hmVnP2kfX1oc+mtx+XWLA=
+github.com/kylelemons/godebug v1.1.0 
h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod 
h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod 
h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 
h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
+google.golang.org/genproto/googleapis/rpc 
v0.0.0-20240528184218-531527333157/go.mod 
h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
+google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
+google.golang.org/grpc v1.65.0/go.mod 
h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
+google.golang.org/protobuf v1.34.2 
h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
+google.golang.org/protobuf v1.34.2/go.mod 
h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
diff --git a/modules/agent-framework/airavata-fuse/src/grpcfs/grpc.go 
b/modules/agent-framework/airavata-fuse/src/grpcfs/grpc.go
new file mode 100644
index 0000000000..eab17997d0
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs/grpc.go
@@ -0,0 +1,112 @@
+// place for grpc calls
+
+package grpcfs
+
+import (
+       "context"
+       pb "grpcfs/pb"
+       "io/fs"
+       "log"
+       "time"
+
+       "google.golang.org/protobuf/types/known/timestamppb"
+)
+
+var ctxt = &pb.RPCContext{}
+
+func getStatFs(fsClient pb.FuseServiceClient, ctx context.Context, root 
string) (*pb.StatFs, error) {
+       req := &pb.StatFsReq{
+               Name:    root,
+               Context: ctxt,
+       }
+       res, err := fsClient.StatFs(ctx, req)
+       if err != nil {
+               return nil, err
+       }
+       raw := res.Result
+       if raw == nil {
+               return nil, ctx.Err()
+       }
+       return raw, err
+}
+
+func getStat(fsClient pb.FuseServiceClient, ctx context.Context, path string) 
(fs.FileInfo, error) {
+       log.Print("grpc.getStat - path=", path)
+       req := &pb.FileInfoReq{
+               Name:    path,
+               Context: ctxt,
+       }
+       log.Print("grpc.getStat - calling fsClient.FileInfo for ", path)
+       res, err := fsClient.FileInfo(ctx, req)
+       if err != nil {
+               log.Print("grpc.getStat - fsClient.FileInfo raised error. ", 
err)
+               return nil, err
+       }
+       raw := res.Result
+       if raw == nil {
+               return nil, ctx.Err()
+       }
+       result := &FileInfoBridge{info: *raw}
+       return result, err
+}
+
+func readDir(fsClient pb.FuseServiceClient, ctx context.Context, path string) 
([]fs.DirEntry, error) {
+       req := &pb.ReadDirReq{
+               Name:    path,
+               Context: ctxt,
+       }
+       res, err := fsClient.ReadDir(ctx, req)
+       if err != nil {
+               log.Print("grpc.readDir - fsClient.ReadDir raised error. ", err)
+               return nil, err
+       }
+       raw := res.Result
+       var entries []fs.DirEntry
+       for _, entry := range raw {
+               entries = append(entries, &DirEntryBridge{info: *entry})
+       }
+       return entries, err
+}
+
+func readFile(fsClient pb.FuseServiceClient, ctx context.Context, path string) 
([]byte, error) {
+       req := &pb.ReadFileReq{
+               Name:    path,
+               Context: ctxt,
+       }
+       res, err := fsClient.ReadFile(ctx, req)
+       return res.Result.Dst, err
+}
+
+func writeFile(fsClient pb.FuseServiceClient, ctx context.Context, path 
string, data []byte, offset int64) (bool, error) {
+       req := &pb.WriteFileReq{
+               Name:    path,
+               Context: ctxt,
+       }
+       res, err := fsClient.WriteFile(ctx, req)
+       return res.Result, err
+}
+
+func setInodeAttributes(fsClient pb.FuseServiceClient, ctx context.Context, 
path string, size *uint64, mode *uint32, atime *time.Time, mtime *time.Time) 
(*pb.InodeAtt, error) {
+       var at *timestamppb.Timestamp
+       var mt *timestamppb.Timestamp
+       if atime != nil {
+               at = timestamppb.New(*atime)
+       }
+       if mtime != nil {
+               mt = timestamppb.New(*mtime)
+       }
+       req := &pb.SetInodeAttReq{
+               Name:     path,
+               Context:  ctxt,
+               Size:     size,
+               FileMode: mode,
+               ATime:    at,
+               MTime:    mt,
+       }
+       res, err := fsClient.SetInodeAtt(ctx, req)
+       if err != nil {
+               log.Print("grpc.setInodeAttributes - fsClient.SetInodeAtt 
raised error. ", err)
+               return nil, err
+       }
+       return res.Result, err
+}
diff --git a/modules/agent-framework/airavata-fuse/src/grpcfs/inode.go 
b/modules/agent-framework/airavata-fuse/src/grpcfs/inode.go
new file mode 100644
index 0000000000..1502ba651f
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs/inode.go
@@ -0,0 +1,149 @@
+// place for data-side helper functions
+
+package grpcfs
+
+import (
+       "context"
+       "fmt"
+       "grpcfs/pb"
+       "log"
+       "os"
+       "path/filepath"
+       "sync"
+       "sync/atomic"
+
+       "github.com/jacobsa/fuse/fuseops"
+       "github.com/jacobsa/fuse/fuseutil"
+)
+
+var (
+       uid                     = uint32(os.Getuid())
+       gid                     = uint32(os.Getgid())
+       allocatedInodeId uint64 = fuseops.RootInodeID
+)
+
+type Inode interface {
+       Id() fuseops.InodeID
+       Path() string
+       String() string
+       Attributes() (*fuseops.InodeAttributes, error)
+       ListChildren(inodes *sync.Map) ([]*fuseutil.Dirent, error)
+       Contents() ([]byte, error)
+}
+
+func getOrCreateInode(inodes *sync.Map, fsClient pb.FuseServiceClient, ctx 
context.Context, parentId fuseops.InodeID, name string) (Inode, error) {
+       log.Print("inode.getOrCreateInode - called. ", name)
+       parent, found := inodes.Load(parentId)
+       if !found {
+               log.Print("inode.getOrCreateInode - no parent Inode: ", 
parentId)
+               return nil, nil
+       }
+       parentPath := parent.(Inode).Path()
+       path := filepath.Join(parentPath, name)
+       log.Print("inode.getOrCreateInode - resolved path: ", path)
+
+       fileInfo, err := getStat(fsClient, ctx, path)
+       if err != nil {
+               log.Print("inode.getOrCreateInode - no path stats: ", path)
+               return nil, err
+       }
+       log.Print("inode.getOrCreateInode - got file stats: ", path, fileInfo)
+       // stat, _ := fileInfo.Sys().(*Sys)
+
+       entry, _ := NewInode(path, fsClient)
+       // entry := &inodeEntry{
+       //      id:     fuseops.InodeID(stat.Ino),
+       //      path:   path,
+       //      client: fsClient,
+       // }
+       storedEntry, _ := inodes.LoadOrStore(entry.Id(), entry)
+       return storedEntry.(Inode), nil
+}
+
+func nextInodeID() (next fuseops.InodeID) {
+       nextInodeId := atomic.AddUint64(&allocatedInodeId, 1)
+       return fuseops.InodeID(nextInodeId)
+}
+
+type inodeEntry struct {
+       id     fuseops.InodeID
+       path   string
+       client pb.FuseServiceClient
+}
+
+func NewInode(path string, client pb.FuseServiceClient) (Inode, error) {
+       return &inodeEntry{
+               id:     nextInodeID(),
+               path:   path,
+               client: client,
+       }, nil
+}
+
+func (in *inodeEntry) Id() fuseops.InodeID {
+       return in.id
+}
+
+func (in *inodeEntry) Path() string {
+       return in.path
+}
+
+func (in *inodeEntry) String() string {
+       return fmt.Sprintf("%v::%v", in.id, in.path)
+}
+
+func (in *inodeEntry) Attributes() (*fuseops.InodeAttributes, error) {
+       log.Print("inodeEntry.Attributes - called. ", in.path)
+       fileInfo, err := getStat(in.client, context.TODO(), in.path)
+       if err != nil {
+               return &fuseops.InodeAttributes{}, err
+       }
+
+       return &fuseops.InodeAttributes{
+               Size:  uint64(fileInfo.Size()),
+               Nlink: 1,
+               Mode:  fileInfo.Mode(),
+               Mtime: fileInfo.ModTime(),
+               Uid:   uid,
+               Gid:   gid,
+       }, nil
+}
+
+func (in *inodeEntry) ListChildren(inodes *sync.Map) ([]*fuseutil.Dirent, 
error) {
+       log.Print("inodeEntry.ListChildren - called. ", in.path)
+       children, err := readDir(in.client, context.TODO(), in.path)
+       if err != nil {
+               log.Print("inodeEntry.ListChildren - error in readDir. ", 
in.path)
+               return nil, err
+       }
+       dirents := []*fuseutil.Dirent{}
+       for i, child := range children {
+
+               childInode, err := getOrCreateInode(inodes, in.client, 
context.TODO(), in.id, child.Name())
+               if err != nil || childInode == nil {
+                       continue
+               }
+
+               var childType fuseutil.DirentType
+               if child.IsDir() {
+                       childType = fuseutil.DT_Directory
+               } else if child.Type()&os.ModeSymlink != 0 {
+                       childType = fuseutil.DT_Link
+               } else {
+                       childType = fuseutil.DT_File
+               }
+
+               dirents = append(dirents, &fuseutil.Dirent{
+                       Offset: fuseops.DirOffset(i + 1),
+                       Inode:  childInode.Id(),
+                       Name:   child.Name(),
+                       Type:   childType,
+               })
+       }
+       return dirents, nil
+}
+
+func (in *inodeEntry) Contents() ([]byte, error) {
+       log.Print("inodeEntry.Contents - called. ", in.path)
+       res, err := readFile(in.client, context.TODO(), in.path)
+       return res, err
+}
diff --git a/modules/agent-framework/airavata-fuse/src/grpcfs/pb/grpcfs.pb.go 
b/modules/agent-framework/airavata-fuse/src/grpcfs/pb/grpcfs.pb.go
new file mode 100644
index 0000000000..85ee6a14eb
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs/pb/grpcfs.pb.go
@@ -0,0 +1,2253 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+//     protoc-gen-go v1.34.2
+//     protoc        v5.27.1
+// source: proto/grpcfs.proto
+
+package pb
+
+import (
+       protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+       protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+       timestamppb "google.golang.org/protobuf/types/known/timestamppb"
+       reflect "reflect"
+       sync "sync"
+)
+
+const (
+       // Verify that this generated code is sufficiently up-to-date.
+       _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+       // Verify that runtime/protoimpl is sufficiently up-to-date.
+       _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// RPC Helper Context - Define as needed
+type RPCContext struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       GatewayId   string `protobuf:"bytes,1,opt,name=GatewayId,proto3" 
json:"GatewayId,omitempty"`
+       AccessToken string `protobuf:"bytes,2,opt,name=AccessToken,proto3" 
json:"AccessToken,omitempty"`
+       AgentId     string `protobuf:"bytes,3,opt,name=AgentId,proto3" 
json:"AgentId,omitempty"`
+}
+
+func (x *RPCContext) Reset() {
+       *x = RPCContext{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[0]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *RPCContext) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*RPCContext) ProtoMessage() {}
+
+func (x *RPCContext) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[0]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use RPCContext.ProtoReflect.Descriptor instead.
+func (*RPCContext) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *RPCContext) GetGatewayId() string {
+       if x != nil {
+               return x.GatewayId
+       }
+       return ""
+}
+
+func (x *RPCContext) GetAccessToken() string {
+       if x != nil {
+               return x.AccessToken
+       }
+       return ""
+}
+
+func (x *RPCContext) GetAgentId() string {
+       if x != nil {
+               return x.AgentId
+       }
+       return ""
+}
+
+// Primitive
+type OpContext struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       FuseId uint64 `protobuf:"varint,1,opt,name=FuseId,proto3" 
json:"FuseId,omitempty"`
+       Pid    uint64 `protobuf:"varint,2,opt,name=Pid,proto3" 
json:"Pid,omitempty"`
+       Uid    uint64 `protobuf:"varint,3,opt,name=Uid,proto3" 
json:"Uid,omitempty"`
+}
+
+func (x *OpContext) Reset() {
+       *x = OpContext{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[1]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *OpContext) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*OpContext) ProtoMessage() {}
+
+func (x *OpContext) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[1]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use OpContext.ProtoReflect.Descriptor instead.
+func (*OpContext) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *OpContext) GetFuseId() uint64 {
+       if x != nil {
+               return x.FuseId
+       }
+       return 0
+}
+
+func (x *OpContext) GetPid() uint64 {
+       if x != nil {
+               return x.Pid
+       }
+       return 0
+}
+
+func (x *OpContext) GetUid() uint64 {
+       if x != nil {
+               return x.Uid
+       }
+       return 0
+}
+
+// Toplevel
+type StatFs struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       BlockSize       uint32 `protobuf:"varint,1,opt,name=BlockSize,proto3" 
json:"BlockSize,omitempty"`
+       Blocks          uint64 `protobuf:"varint,2,opt,name=Blocks,proto3" 
json:"Blocks,omitempty"`
+       BlocksFree      uint64 `protobuf:"varint,3,opt,name=BlocksFree,proto3" 
json:"BlocksFree,omitempty"`
+       BlocksAvailable uint64 
`protobuf:"varint,4,opt,name=BlocksAvailable,proto3" 
json:"BlocksAvailable,omitempty"`
+       IoSize          uint32 `protobuf:"varint,5,opt,name=IoSize,proto3" 
json:"IoSize,omitempty"`
+       Inodes          uint64 `protobuf:"varint,6,opt,name=Inodes,proto3" 
json:"Inodes,omitempty"`
+       InodesFree      uint64 `protobuf:"varint,7,opt,name=InodesFree,proto3" 
json:"InodesFree,omitempty"`
+}
+
+func (x *StatFs) Reset() {
+       *x = StatFs{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[2]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *StatFs) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*StatFs) ProtoMessage() {}
+
+func (x *StatFs) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[2]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use StatFs.ProtoReflect.Descriptor instead.
+func (*StatFs) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *StatFs) GetBlockSize() uint32 {
+       if x != nil {
+               return x.BlockSize
+       }
+       return 0
+}
+
+func (x *StatFs) GetBlocks() uint64 {
+       if x != nil {
+               return x.Blocks
+       }
+       return 0
+}
+
+func (x *StatFs) GetBlocksFree() uint64 {
+       if x != nil {
+               return x.BlocksFree
+       }
+       return 0
+}
+
+func (x *StatFs) GetBlocksAvailable() uint64 {
+       if x != nil {
+               return x.BlocksAvailable
+       }
+       return 0
+}
+
+func (x *StatFs) GetIoSize() uint32 {
+       if x != nil {
+               return x.IoSize
+       }
+       return 0
+}
+
+func (x *StatFs) GetInodes() uint64 {
+       if x != nil {
+               return x.Inodes
+       }
+       return 0
+}
+
+func (x *StatFs) GetInodesFree() uint64 {
+       if x != nil {
+               return x.InodesFree
+       }
+       return 0
+}
+
+type FileInfo struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Name    string                 `protobuf:"bytes,1,opt,name=Name,proto3" 
json:"Name,omitempty"`
+       Size    int64                  
`protobuf:"varint,2,opt,name=Size,proto3" json:"Size,omitempty"`
+       Mode    uint32                 
`protobuf:"varint,3,opt,name=Mode,proto3" json:"Mode,omitempty"`
+       ModTime *timestamppb.Timestamp 
`protobuf:"bytes,4,opt,name=ModTime,proto3" json:"ModTime,omitempty"`
+       IsDir   bool                   
`protobuf:"varint,5,opt,name=IsDir,proto3" json:"IsDir,omitempty"`
+       Ino     uint64                 `protobuf:"varint,6,opt,name=Ino,proto3" 
json:"Ino,omitempty"`
+}
+
+func (x *FileInfo) Reset() {
+       *x = FileInfo{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[3]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *FileInfo) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FileInfo) ProtoMessage() {}
+
+func (x *FileInfo) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[3]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use FileInfo.ProtoReflect.Descriptor instead.
+func (*FileInfo) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *FileInfo) GetName() string {
+       if x != nil {
+               return x.Name
+       }
+       return ""
+}
+
+func (x *FileInfo) GetSize() int64 {
+       if x != nil {
+               return x.Size
+       }
+       return 0
+}
+
+func (x *FileInfo) GetMode() uint32 {
+       if x != nil {
+               return x.Mode
+       }
+       return 0
+}
+
+func (x *FileInfo) GetModTime() *timestamppb.Timestamp {
+       if x != nil {
+               return x.ModTime
+       }
+       return nil
+}
+
+func (x *FileInfo) GetIsDir() bool {
+       if x != nil {
+               return x.IsDir
+       }
+       return false
+}
+
+func (x *FileInfo) GetIno() uint64 {
+       if x != nil {
+               return x.Ino
+       }
+       return 0
+}
+
+type OpenedDir struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Inode     uint64     `protobuf:"varint,1,opt,name=Inode,proto3" 
json:"Inode,omitempty"`
+       Handle    uint64     `protobuf:"varint,2,opt,name=Handle,proto3" 
json:"Handle,omitempty"`
+       OpContext *OpContext `protobuf:"bytes,3,opt,name=OpContext,proto3" 
json:"OpContext,omitempty"`
+       CacheDir  bool       `protobuf:"varint,4,opt,name=CacheDir,proto3" 
json:"CacheDir,omitempty"`
+       KeepCache bool       `protobuf:"varint,5,opt,name=KeepCache,proto3" 
json:"KeepCache,omitempty"`
+}
+
+func (x *OpenedDir) Reset() {
+       *x = OpenedDir{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[4]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *OpenedDir) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*OpenedDir) ProtoMessage() {}
+
+func (x *OpenedDir) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[4]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use OpenedDir.ProtoReflect.Descriptor instead.
+func (*OpenedDir) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *OpenedDir) GetInode() uint64 {
+       if x != nil {
+               return x.Inode
+       }
+       return 0
+}
+
+func (x *OpenedDir) GetHandle() uint64 {
+       if x != nil {
+               return x.Handle
+       }
+       return 0
+}
+
+func (x *OpenedDir) GetOpContext() *OpContext {
+       if x != nil {
+               return x.OpContext
+       }
+       return nil
+}
+
+func (x *OpenedDir) GetCacheDir() bool {
+       if x != nil {
+               return x.CacheDir
+       }
+       return false
+}
+
+func (x *OpenedDir) GetKeepCache() bool {
+       if x != nil {
+               return x.KeepCache
+       }
+       return false
+}
+
+type OpenedFile struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Inode         uint64     `protobuf:"varint,1,opt,name=Inode,proto3" 
json:"Inode,omitempty"`
+       Handle        uint64     `protobuf:"varint,2,opt,name=Handle,proto3" 
json:"Handle,omitempty"`
+       KeepPageCache bool       
`protobuf:"varint,3,opt,name=KeepPageCache,proto3" 
json:"KeepPageCache,omitempty"`
+       UseDirectIO   bool       
`protobuf:"varint,4,opt,name=UseDirectIO,proto3" json:"UseDirectIO,omitempty"`
+       OpenFlags     uint32     `protobuf:"varint,5,opt,name=OpenFlags,proto3" 
json:"OpenFlags,omitempty"`
+       OpContext     *OpContext `protobuf:"bytes,6,opt,name=OpContext,proto3" 
json:"OpContext,omitempty"`
+}
+
+func (x *OpenedFile) Reset() {
+       *x = OpenedFile{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[5]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *OpenedFile) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*OpenedFile) ProtoMessage() {}
+
+func (x *OpenedFile) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[5]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use OpenedFile.ProtoReflect.Descriptor instead.
+func (*OpenedFile) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *OpenedFile) GetInode() uint64 {
+       if x != nil {
+               return x.Inode
+       }
+       return 0
+}
+
+func (x *OpenedFile) GetHandle() uint64 {
+       if x != nil {
+               return x.Handle
+       }
+       return 0
+}
+
+func (x *OpenedFile) GetKeepPageCache() bool {
+       if x != nil {
+               return x.KeepPageCache
+       }
+       return false
+}
+
+func (x *OpenedFile) GetUseDirectIO() bool {
+       if x != nil {
+               return x.UseDirectIO
+       }
+       return false
+}
+
+func (x *OpenedFile) GetOpenFlags() uint32 {
+       if x != nil {
+               return x.OpenFlags
+       }
+       return 0
+}
+
+func (x *OpenedFile) GetOpContext() *OpContext {
+       if x != nil {
+               return x.OpContext
+       }
+       return nil
+}
+
+type DirEntry struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Name     string    `protobuf:"bytes,1,opt,name=Name,proto3" 
json:"Name,omitempty"`
+       IsDir    bool      `protobuf:"varint,2,opt,name=IsDir,proto3" 
json:"IsDir,omitempty"`
+       FileMode uint32    `protobuf:"varint,3,opt,name=FileMode,proto3" 
json:"FileMode,omitempty"`
+       Info     *FileInfo `protobuf:"bytes,4,opt,name=Info,proto3" 
json:"Info,omitempty"`
+}
+
+func (x *DirEntry) Reset() {
+       *x = DirEntry{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[6]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *DirEntry) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DirEntry) ProtoMessage() {}
+
+func (x *DirEntry) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[6]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use DirEntry.ProtoReflect.Descriptor instead.
+func (*DirEntry) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *DirEntry) GetName() string {
+       if x != nil {
+               return x.Name
+       }
+       return ""
+}
+
+func (x *DirEntry) GetIsDir() bool {
+       if x != nil {
+               return x.IsDir
+       }
+       return false
+}
+
+func (x *DirEntry) GetFileMode() uint32 {
+       if x != nil {
+               return x.FileMode
+       }
+       return 0
+}
+
+func (x *DirEntry) GetInfo() *FileInfo {
+       if x != nil {
+               return x.Info
+       }
+       return nil
+}
+
+type FileEntry struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Inode     uint64     `protobuf:"varint,1,opt,name=Inode,proto3" 
json:"Inode,omitempty"`
+       Handle    uint64     `protobuf:"varint,2,opt,name=Handle,proto3" 
json:"Handle,omitempty"`
+       Offset    int64      `protobuf:"varint,3,opt,name=Offset,proto3" 
json:"Offset,omitempty"`
+       Size      int64      `protobuf:"varint,4,opt,name=Size,proto3" 
json:"Size,omitempty"`
+       Dst       []byte     `protobuf:"bytes,5,opt,name=Dst,proto3" 
json:"Dst,omitempty"`
+       Data      [][]byte   `protobuf:"bytes,6,rep,name=Data,proto3" 
json:"Data,omitempty"`
+       BytesRead int32      `protobuf:"varint,7,opt,name=BytesRead,proto3" 
json:"BytesRead,omitempty"`
+       OpContext *OpContext `protobuf:"bytes,8,opt,name=OpContext,proto3" 
json:"OpContext,omitempty"`
+}
+
+func (x *FileEntry) Reset() {
+       *x = FileEntry{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[7]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *FileEntry) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FileEntry) ProtoMessage() {}
+
+func (x *FileEntry) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[7]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use FileEntry.ProtoReflect.Descriptor instead.
+func (*FileEntry) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *FileEntry) GetInode() uint64 {
+       if x != nil {
+               return x.Inode
+       }
+       return 0
+}
+
+func (x *FileEntry) GetHandle() uint64 {
+       if x != nil {
+               return x.Handle
+       }
+       return 0
+}
+
+func (x *FileEntry) GetOffset() int64 {
+       if x != nil {
+               return x.Offset
+       }
+       return 0
+}
+
+func (x *FileEntry) GetSize() int64 {
+       if x != nil {
+               return x.Size
+       }
+       return 0
+}
+
+func (x *FileEntry) GetDst() []byte {
+       if x != nil {
+               return x.Dst
+       }
+       return nil
+}
+
+func (x *FileEntry) GetData() [][]byte {
+       if x != nil {
+               return x.Data
+       }
+       return nil
+}
+
+func (x *FileEntry) GetBytesRead() int32 {
+       if x != nil {
+               return x.BytesRead
+       }
+       return 0
+}
+
+func (x *FileEntry) GetOpContext() *OpContext {
+       if x != nil {
+               return x.OpContext
+       }
+       return nil
+}
+
+type InodeAtt struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Size     uint64                 
`protobuf:"varint,1,opt,name=Size,proto3" json:"Size,omitempty"`
+       Nlink    uint32                 
`protobuf:"varint,2,opt,name=Nlink,proto3" json:"Nlink,omitempty"`
+       FileMode uint32                 
`protobuf:"varint,3,opt,name=FileMode,proto3" json:"FileMode,omitempty"`
+       Atime    *timestamppb.Timestamp 
`protobuf:"bytes,5,opt,name=Atime,proto3" json:"Atime,omitempty"`
+       Mtime    *timestamppb.Timestamp 
`protobuf:"bytes,6,opt,name=Mtime,proto3" json:"Mtime,omitempty"`
+       Ctime    *timestamppb.Timestamp 
`protobuf:"bytes,7,opt,name=Ctime,proto3" json:"Ctime,omitempty"`
+}
+
+func (x *InodeAtt) Reset() {
+       *x = InodeAtt{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[8]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *InodeAtt) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*InodeAtt) ProtoMessage() {}
+
+func (x *InodeAtt) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[8]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use InodeAtt.ProtoReflect.Descriptor instead.
+func (*InodeAtt) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{8}
+}
+
+func (x *InodeAtt) GetSize() uint64 {
+       if x != nil {
+               return x.Size
+       }
+       return 0
+}
+
+func (x *InodeAtt) GetNlink() uint32 {
+       if x != nil {
+               return x.Nlink
+       }
+       return 0
+}
+
+func (x *InodeAtt) GetFileMode() uint32 {
+       if x != nil {
+               return x.FileMode
+       }
+       return 0
+}
+
+func (x *InodeAtt) GetAtime() *timestamppb.Timestamp {
+       if x != nil {
+               return x.Atime
+       }
+       return nil
+}
+
+func (x *InodeAtt) GetMtime() *timestamppb.Timestamp {
+       if x != nil {
+               return x.Mtime
+       }
+       return nil
+}
+
+func (x *InodeAtt) GetCtime() *timestamppb.Timestamp {
+       if x != nil {
+               return x.Ctime
+       }
+       return nil
+}
+
+// Request Bodies
+type StatFsReq struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Name    string      `protobuf:"bytes,1,opt,name=Name,proto3" 
json:"Name,omitempty"`
+       Context *RPCContext `protobuf:"bytes,2,opt,name=Context,proto3" 
json:"Context,omitempty"`
+}
+
+func (x *StatFsReq) Reset() {
+       *x = StatFsReq{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[9]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *StatFsReq) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*StatFsReq) ProtoMessage() {}
+
+func (x *StatFsReq) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[9]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use StatFsReq.ProtoReflect.Descriptor instead.
+func (*StatFsReq) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *StatFsReq) GetName() string {
+       if x != nil {
+               return x.Name
+       }
+       return ""
+}
+
+func (x *StatFsReq) GetContext() *RPCContext {
+       if x != nil {
+               return x.Context
+       }
+       return nil
+}
+
+type FileInfoReq struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Name    string      `protobuf:"bytes,1,opt,name=Name,proto3" 
json:"Name,omitempty"`
+       Context *RPCContext `protobuf:"bytes,2,opt,name=Context,proto3" 
json:"Context,omitempty"`
+}
+
+func (x *FileInfoReq) Reset() {
+       *x = FileInfoReq{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[10]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *FileInfoReq) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FileInfoReq) ProtoMessage() {}
+
+func (x *FileInfoReq) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[10]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use FileInfoReq.ProtoReflect.Descriptor instead.
+func (*FileInfoReq) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *FileInfoReq) GetName() string {
+       if x != nil {
+               return x.Name
+       }
+       return ""
+}
+
+func (x *FileInfoReq) GetContext() *RPCContext {
+       if x != nil {
+               return x.Context
+       }
+       return nil
+}
+
+type OpenDirReq struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Name    string      `protobuf:"bytes,1,opt,name=Name,proto3" 
json:"Name,omitempty"`
+       Context *RPCContext `protobuf:"bytes,2,opt,name=Context,proto3" 
json:"Context,omitempty"`
+}
+
+func (x *OpenDirReq) Reset() {
+       *x = OpenDirReq{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[11]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *OpenDirReq) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*OpenDirReq) ProtoMessage() {}
+
+func (x *OpenDirReq) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[11]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use OpenDirReq.ProtoReflect.Descriptor instead.
+func (*OpenDirReq) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *OpenDirReq) GetName() string {
+       if x != nil {
+               return x.Name
+       }
+       return ""
+}
+
+func (x *OpenDirReq) GetContext() *RPCContext {
+       if x != nil {
+               return x.Context
+       }
+       return nil
+}
+
+type OpenFileReq struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Name    string      `protobuf:"bytes,1,opt,name=Name,proto3" 
json:"Name,omitempty"`
+       Context *RPCContext `protobuf:"bytes,2,opt,name=Context,proto3" 
json:"Context,omitempty"`
+}
+
+func (x *OpenFileReq) Reset() {
+       *x = OpenFileReq{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[12]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *OpenFileReq) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*OpenFileReq) ProtoMessage() {}
+
+func (x *OpenFileReq) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[12]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use OpenFileReq.ProtoReflect.Descriptor instead.
+func (*OpenFileReq) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *OpenFileReq) GetName() string {
+       if x != nil {
+               return x.Name
+       }
+       return ""
+}
+
+func (x *OpenFileReq) GetContext() *RPCContext {
+       if x != nil {
+               return x.Context
+       }
+       return nil
+}
+
+type ReadDirReq struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Name    string      `protobuf:"bytes,1,opt,name=Name,proto3" 
json:"Name,omitempty"`
+       Context *RPCContext `protobuf:"bytes,2,opt,name=Context,proto3" 
json:"Context,omitempty"`
+}
+
+func (x *ReadDirReq) Reset() {
+       *x = ReadDirReq{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[13]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ReadDirReq) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ReadDirReq) ProtoMessage() {}
+
+func (x *ReadDirReq) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[13]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use ReadDirReq.ProtoReflect.Descriptor instead.
+func (*ReadDirReq) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{13}
+}
+
+func (x *ReadDirReq) GetName() string {
+       if x != nil {
+               return x.Name
+       }
+       return ""
+}
+
+func (x *ReadDirReq) GetContext() *RPCContext {
+       if x != nil {
+               return x.Context
+       }
+       return nil
+}
+
+type ReadFileReq struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Name    string      `protobuf:"bytes,1,opt,name=Name,proto3" 
json:"Name,omitempty"`
+       Context *RPCContext `protobuf:"bytes,2,opt,name=Context,proto3" 
json:"Context,omitempty"`
+}
+
+func (x *ReadFileReq) Reset() {
+       *x = ReadFileReq{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[14]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ReadFileReq) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ReadFileReq) ProtoMessage() {}
+
+func (x *ReadFileReq) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[14]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use ReadFileReq.ProtoReflect.Descriptor instead.
+func (*ReadFileReq) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{14}
+}
+
+func (x *ReadFileReq) GetName() string {
+       if x != nil {
+               return x.Name
+       }
+       return ""
+}
+
+func (x *ReadFileReq) GetContext() *RPCContext {
+       if x != nil {
+               return x.Context
+       }
+       return nil
+}
+
+type WriteFileReq struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Name    string      `protobuf:"bytes,1,opt,name=Name,proto3" 
json:"Name,omitempty"`
+       Context *RPCContext `protobuf:"bytes,2,opt,name=Context,proto3" 
json:"Context,omitempty"`
+       Data    []byte      `protobuf:"bytes,3,opt,name=Data,proto3" 
json:"Data,omitempty"`
+       Offset  int64       `protobuf:"varint,4,opt,name=Offset,proto3" 
json:"Offset,omitempty"`
+}
+
+func (x *WriteFileReq) Reset() {
+       *x = WriteFileReq{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[15]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *WriteFileReq) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*WriteFileReq) ProtoMessage() {}
+
+func (x *WriteFileReq) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[15]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use WriteFileReq.ProtoReflect.Descriptor instead.
+func (*WriteFileReq) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{15}
+}
+
+func (x *WriteFileReq) GetName() string {
+       if x != nil {
+               return x.Name
+       }
+       return ""
+}
+
+func (x *WriteFileReq) GetContext() *RPCContext {
+       if x != nil {
+               return x.Context
+       }
+       return nil
+}
+
+func (x *WriteFileReq) GetData() []byte {
+       if x != nil {
+               return x.Data
+       }
+       return nil
+}
+
+func (x *WriteFileReq) GetOffset() int64 {
+       if x != nil {
+               return x.Offset
+       }
+       return 0
+}
+
+type SetInodeAttReq struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Name     string                 
`protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"`
+       Context  *RPCContext            
`protobuf:"bytes,2,opt,name=Context,proto3" json:"Context,omitempty"`
+       Size     *uint64                
`protobuf:"varint,3,opt,name=Size,proto3,oneof" json:"Size,omitempty"`
+       FileMode *uint32                
`protobuf:"varint,4,opt,name=FileMode,proto3,oneof" json:"FileMode,omitempty"`
+       ATime    *timestamppb.Timestamp 
`protobuf:"bytes,5,opt,name=ATime,proto3,oneof" json:"ATime,omitempty"`
+       MTime    *timestamppb.Timestamp 
`protobuf:"bytes,6,opt,name=MTime,proto3,oneof" json:"MTime,omitempty"`
+}
+
+func (x *SetInodeAttReq) Reset() {
+       *x = SetInodeAttReq{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[16]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *SetInodeAttReq) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SetInodeAttReq) ProtoMessage() {}
+
+func (x *SetInodeAttReq) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[16]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use SetInodeAttReq.ProtoReflect.Descriptor instead.
+func (*SetInodeAttReq) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{16}
+}
+
+func (x *SetInodeAttReq) GetName() string {
+       if x != nil {
+               return x.Name
+       }
+       return ""
+}
+
+func (x *SetInodeAttReq) GetContext() *RPCContext {
+       if x != nil {
+               return x.Context
+       }
+       return nil
+}
+
+func (x *SetInodeAttReq) GetSize() uint64 {
+       if x != nil && x.Size != nil {
+               return *x.Size
+       }
+       return 0
+}
+
+func (x *SetInodeAttReq) GetFileMode() uint32 {
+       if x != nil && x.FileMode != nil {
+               return *x.FileMode
+       }
+       return 0
+}
+
+func (x *SetInodeAttReq) GetATime() *timestamppb.Timestamp {
+       if x != nil {
+               return x.ATime
+       }
+       return nil
+}
+
+func (x *SetInodeAttReq) GetMTime() *timestamppb.Timestamp {
+       if x != nil {
+               return x.MTime
+       }
+       return nil
+}
+
+// Response Bodies
+type StatFsRes struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Result *StatFs `protobuf:"bytes,1,opt,name=Result,proto3" 
json:"Result,omitempty"`
+}
+
+func (x *StatFsRes) Reset() {
+       *x = StatFsRes{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[17]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *StatFsRes) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*StatFsRes) ProtoMessage() {}
+
+func (x *StatFsRes) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[17]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use StatFsRes.ProtoReflect.Descriptor instead.
+func (*StatFsRes) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{17}
+}
+
+func (x *StatFsRes) GetResult() *StatFs {
+       if x != nil {
+               return x.Result
+       }
+       return nil
+}
+
+type FileInfoRes struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Result *FileInfo `protobuf:"bytes,1,opt,name=Result,proto3" 
json:"Result,omitempty"`
+}
+
+func (x *FileInfoRes) Reset() {
+       *x = FileInfoRes{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[18]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *FileInfoRes) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FileInfoRes) ProtoMessage() {}
+
+func (x *FileInfoRes) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[18]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use FileInfoRes.ProtoReflect.Descriptor instead.
+func (*FileInfoRes) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{18}
+}
+
+func (x *FileInfoRes) GetResult() *FileInfo {
+       if x != nil {
+               return x.Result
+       }
+       return nil
+}
+
+type OpenDirRes struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Result *OpenedDir `protobuf:"bytes,1,opt,name=Result,proto3" 
json:"Result,omitempty"`
+}
+
+func (x *OpenDirRes) Reset() {
+       *x = OpenDirRes{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[19]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *OpenDirRes) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*OpenDirRes) ProtoMessage() {}
+
+func (x *OpenDirRes) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[19]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use OpenDirRes.ProtoReflect.Descriptor instead.
+func (*OpenDirRes) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{19}
+}
+
+func (x *OpenDirRes) GetResult() *OpenedDir {
+       if x != nil {
+               return x.Result
+       }
+       return nil
+}
+
+type OpenFileRes struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Result *OpenedFile `protobuf:"bytes,1,opt,name=Result,proto3" 
json:"Result,omitempty"`
+}
+
+func (x *OpenFileRes) Reset() {
+       *x = OpenFileRes{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[20]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *OpenFileRes) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*OpenFileRes) ProtoMessage() {}
+
+func (x *OpenFileRes) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[20]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use OpenFileRes.ProtoReflect.Descriptor instead.
+func (*OpenFileRes) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{20}
+}
+
+func (x *OpenFileRes) GetResult() *OpenedFile {
+       if x != nil {
+               return x.Result
+       }
+       return nil
+}
+
+type ReadDirRes struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Result []*DirEntry `protobuf:"bytes,1,rep,name=Result,proto3" 
json:"Result,omitempty"`
+}
+
+func (x *ReadDirRes) Reset() {
+       *x = ReadDirRes{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[21]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ReadDirRes) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ReadDirRes) ProtoMessage() {}
+
+func (x *ReadDirRes) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[21]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use ReadDirRes.ProtoReflect.Descriptor instead.
+func (*ReadDirRes) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{21}
+}
+
+func (x *ReadDirRes) GetResult() []*DirEntry {
+       if x != nil {
+               return x.Result
+       }
+       return nil
+}
+
+type ReadFileRes struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Result *FileEntry `protobuf:"bytes,1,opt,name=Result,proto3" 
json:"Result,omitempty"`
+}
+
+func (x *ReadFileRes) Reset() {
+       *x = ReadFileRes{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[22]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *ReadFileRes) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ReadFileRes) ProtoMessage() {}
+
+func (x *ReadFileRes) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[22]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use ReadFileRes.ProtoReflect.Descriptor instead.
+func (*ReadFileRes) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{22}
+}
+
+func (x *ReadFileRes) GetResult() *FileEntry {
+       if x != nil {
+               return x.Result
+       }
+       return nil
+}
+
+type WriteFileRes struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Result bool `protobuf:"varint,1,opt,name=Result,proto3" 
json:"Result,omitempty"`
+}
+
+func (x *WriteFileRes) Reset() {
+       *x = WriteFileRes{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[23]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *WriteFileRes) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*WriteFileRes) ProtoMessage() {}
+
+func (x *WriteFileRes) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[23]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use WriteFileRes.ProtoReflect.Descriptor instead.
+func (*WriteFileRes) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{23}
+}
+
+func (x *WriteFileRes) GetResult() bool {
+       if x != nil {
+               return x.Result
+       }
+       return false
+}
+
+type SetInodeAttRes struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Result *InodeAtt `protobuf:"bytes,1,opt,name=Result,proto3" 
json:"Result,omitempty"`
+}
+
+func (x *SetInodeAttRes) Reset() {
+       *x = SetInodeAttRes{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_grpcfs_proto_msgTypes[24]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *SetInodeAttRes) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SetInodeAttRes) ProtoMessage() {}
+
+func (x *SetInodeAttRes) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_grpcfs_proto_msgTypes[24]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use SetInodeAttRes.ProtoReflect.Descriptor instead.
+func (*SetInodeAttRes) Descriptor() ([]byte, []int) {
+       return file_proto_grpcfs_proto_rawDescGZIP(), []int{24}
+}
+
+func (x *SetInodeAttRes) GetResult() *InodeAtt {
+       if x != nil {
+               return x.Result
+       }
+       return nil
+}
+
+var File_proto_grpcfs_proto protoreflect.FileDescriptor
+
+var file_proto_grpcfs_proto_rawDesc = []byte{
+       0x0a, 0x12, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x72, 0x70, 0x63, 
0x66, 0x73, 0x2e, 0x70,
+       0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x1f, 0x67, 0x6f, 
0x6f, 0x67, 0x6c, 0x65,
+       0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 
0x6d, 0x65, 0x73, 0x74,
+       0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x66, 0x0a, 
0x0a, 0x52, 0x50, 0x43,
+       0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x47, 
0x61, 0x74, 0x65, 0x77,
+       0x61, 0x79, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 
0x47, 0x61, 0x74, 0x65,
+       0x77, 0x61, 0x79, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x41, 0x63, 0x63, 
0x65, 0x73, 0x73, 0x54,
+       0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 
0x41, 0x63, 0x63, 0x65,
+       0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x41, 
0x67, 0x65, 0x6e, 0x74,
+       0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x41, 0x67, 
0x65, 0x6e, 0x74, 0x49,
+       0x64, 0x22, 0x47, 0x0a, 0x09, 0x4f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x65, 
0x78, 0x74, 0x12, 0x16,
+       0x0a, 0x06, 0x46, 0x75, 0x73, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 
0x28, 0x04, 0x52, 0x06,
+       0x46, 0x75, 0x73, 0x65, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x50, 0x69, 
0x64, 0x18, 0x02, 0x20,
+       0x01, 0x28, 0x04, 0x52, 0x03, 0x50, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 
0x55, 0x69, 0x64, 0x18,
+       0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x55, 0x69, 0x64, 0x22, 0xd8, 
0x01, 0x0a, 0x06, 0x53,
+       0x74, 0x61, 0x74, 0x46, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 
0x63, 0x6b, 0x53, 0x69,
+       0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x42, 0x6c, 
0x6f, 0x63, 0x6b, 0x53,
+       0x69, 0x7a, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 
0x73, 0x18, 0x02, 0x20,
+       0x01, 0x28, 0x04, 0x52, 0x06, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 
0x1e, 0x0a, 0x0a, 0x42,
+       0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x46, 0x72, 0x65, 0x65, 0x18, 0x03, 0x20, 
0x01, 0x28, 0x04, 0x52,
+       0x0a, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x46, 0x72, 0x65, 0x65, 0x12, 
0x28, 0x0a, 0x0f, 0x42,
+       0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 
0x6c, 0x65, 0x18, 0x04,
+       0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 
0x41, 0x76, 0x61, 0x69,
+       0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x6f, 0x53, 
0x69, 0x7a, 0x65, 0x18,
+       0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x49, 0x6f, 0x53, 0x69, 0x7a, 
0x65, 0x12, 0x16, 0x0a,
+       0x06, 0x49, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 
0x04, 0x52, 0x06, 0x49,
+       0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x49, 0x6e, 0x6f, 
0x64, 0x65, 0x73, 0x46,
+       0x72, 0x65, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x49, 
0x6e, 0x6f, 0x64, 0x65,
+       0x73, 0x46, 0x72, 0x65, 0x65, 0x22, 0xa4, 0x01, 0x0a, 0x08, 0x46, 0x69, 
0x6c, 0x65, 0x49, 0x6e,
+       0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 
0x20, 0x01, 0x28, 0x09,
+       0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x53, 0x69, 
0x7a, 0x65, 0x18, 0x02,
+       0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x12, 
0x0a, 0x04, 0x4d, 0x6f,
+       0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x4d, 0x6f, 
0x64, 0x65, 0x12, 0x34,
+       0x0a, 0x07, 0x4d, 0x6f, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 
0x01, 0x28, 0x0b, 0x32,
+       0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 
0x74, 0x6f, 0x62, 0x75,
+       0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 
0x07, 0x4d, 0x6f, 0x64,
+       0x54, 0x69, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x73, 0x44, 0x69, 
0x72, 0x18, 0x05, 0x20,
+       0x01, 0x28, 0x08, 0x52, 0x05, 0x49, 0x73, 0x44, 0x69, 0x72, 0x12, 0x10, 
0x0a, 0x03, 0x49, 0x6e,
+       0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x49, 0x6e, 0x6f, 
0x22, 0xa0, 0x01, 0x0a,
+       0x09, 0x4f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x44, 0x69, 0x72, 0x12, 0x14, 
0x0a, 0x05, 0x49, 0x6e,
+       0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x49, 
0x6e, 0x6f, 0x64, 0x65,
+       0x12, 0x16, 0x0a, 0x06, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x02, 
0x20, 0x01, 0x28, 0x04,
+       0x52, 0x06, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x2b, 0x0a, 0x09, 
0x4f, 0x70, 0x43, 0x6f,
+       0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 
0x0d, 0x2e, 0x70, 0x62,
+       0x2e, 0x4f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x09, 
0x4f, 0x70, 0x43, 0x6f,
+       0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x61, 0x63, 
0x68, 0x65, 0x44, 0x69,
+       0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x43, 0x61, 0x63, 
0x68, 0x65, 0x44, 0x69,
+       0x72, 0x12, 0x1c, 0x0a, 0x09, 0x4b, 0x65, 0x65, 0x70, 0x43, 0x61, 0x63, 
0x68, 0x65, 0x18, 0x05,
+       0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x4b, 0x65, 0x65, 0x70, 0x43, 0x61, 
0x63, 0x68, 0x65, 0x22,
+       0xcd, 0x01, 0x0a, 0x0a, 0x4f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x46, 0x69, 
0x6c, 0x65, 0x12, 0x14,
+       0x0a, 0x05, 0x49, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 
0x04, 0x52, 0x05, 0x49,
+       0x6e, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x61, 0x6e, 0x64, 
0x6c, 0x65, 0x18, 0x02,
+       0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 
0x12, 0x24, 0x0a, 0x0d,
+       0x4b, 0x65, 0x65, 0x70, 0x50, 0x61, 0x67, 0x65, 0x43, 0x61, 0x63, 0x68, 
0x65, 0x18, 0x03, 0x20,
+       0x01, 0x28, 0x08, 0x52, 0x0d, 0x4b, 0x65, 0x65, 0x70, 0x50, 0x61, 0x67, 
0x65, 0x43, 0x61, 0x63,
+       0x68, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x44, 0x69, 0x72, 
0x65, 0x63, 0x74, 0x49,
+       0x4f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x55, 0x73, 0x65, 
0x44, 0x69, 0x72, 0x65,
+       0x63, 0x74, 0x49, 0x4f, 0x12, 0x1c, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x6e, 
0x46, 0x6c, 0x61, 0x67,
+       0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x4f, 0x70, 0x65, 
0x6e, 0x46, 0x6c, 0x61,
+       0x67, 0x73, 0x12, 0x2b, 0x0a, 0x09, 0x4f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 
0x65, 0x78, 0x74, 0x18,
+       0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x4f, 
0x70, 0x43, 0x6f, 0x6e,
+       0x74, 0x65, 0x78, 0x74, 0x52, 0x09, 0x4f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 
0x65, 0x78, 0x74, 0x22,
+       0x72, 0x0a, 0x08, 0x44, 0x69, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 
0x12, 0x0a, 0x04, 0x4e,
+       0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 
0x61, 0x6d, 0x65, 0x12,
+       0x14, 0x0a, 0x05, 0x49, 0x73, 0x44, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 
0x28, 0x08, 0x52, 0x05,
+       0x49, 0x73, 0x44, 0x69, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x69, 0x6c, 
0x65, 0x4d, 0x6f, 0x64,
+       0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x46, 0x69, 0x6c, 
0x65, 0x4d, 0x6f, 0x64,
+       0x65, 0x12, 0x20, 0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 
0x01, 0x28, 0x0b, 0x32,
+       0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 
0x6f, 0x52, 0x04, 0x49,
+       0x6e, 0x66, 0x6f, 0x22, 0xd6, 0x01, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x65, 
0x45, 0x6e, 0x74, 0x72,
+       0x79, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 
0x20, 0x01, 0x28, 0x04,
+       0x52, 0x05, 0x49, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x48, 
0x61, 0x6e, 0x64, 0x6c,
+       0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x48, 0x61, 0x6e, 
0x64, 0x6c, 0x65, 0x12,
+       0x16, 0x0a, 0x06, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 
0x01, 0x28, 0x03, 0x52,
+       0x06, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x53, 
0x69, 0x7a, 0x65, 0x18,
+       0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x12, 
0x10, 0x0a, 0x03, 0x44,
+       0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x44, 0x73, 
0x74, 0x12, 0x12, 0x0a,
+       0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0c, 0x52, 
0x04, 0x44, 0x61, 0x74,
+       0x61, 0x12, 0x1c, 0x0a, 0x09, 0x42, 0x79, 0x74, 0x65, 0x73, 0x52, 0x65, 
0x61, 0x64, 0x18, 0x07,
+       0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x42, 0x79, 0x74, 0x65, 0x73, 0x52, 
0x65, 0x61, 0x64, 0x12,
+       0x2b, 0x0a, 0x09, 0x4f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 
0x18, 0x08, 0x20, 0x01,
+       0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x4f, 0x70, 0x43, 0x6f, 
0x6e, 0x74, 0x65, 0x78,
+       0x74, 0x52, 0x09, 0x4f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 
0x22, 0xe6, 0x01, 0x0a,
+       0x08, 0x49, 0x6e, 0x6f, 0x64, 0x65, 0x41, 0x74, 0x74, 0x12, 0x12, 0x0a, 
0x04, 0x53, 0x69, 0x7a,
+       0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x53, 0x69, 0x7a, 
0x65, 0x12, 0x14, 0x0a,
+       0x05, 0x4e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 
0x52, 0x05, 0x4e, 0x6c,
+       0x69, 0x6e, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x4d, 
0x6f, 0x64, 0x65, 0x18,
+       0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x4d, 
0x6f, 0x64, 0x65, 0x12,
+       0x30, 0x0a, 0x05, 0x41, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 
0x28, 0x0b, 0x32, 0x1a,
+       0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 
0x6f, 0x62, 0x75, 0x66,
+       0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 
0x41, 0x74, 0x69, 0x6d,
+       0x65, 0x12, 0x30, 0x0a, 0x05, 0x4d, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 
0x20, 0x01, 0x28, 0x0b,
+       0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 
0x6f, 0x74, 0x6f, 0x62,
+       0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 
0x52, 0x05, 0x4d, 0x74,
+       0x69, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x43, 0x74, 0x69, 0x6d, 0x65, 
0x18, 0x07, 0x20, 0x01,
+       0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 
0x70, 0x72, 0x6f, 0x74,
+       0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 
0x6d, 0x70, 0x52, 0x05,
+       0x43, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x49, 0x0a, 0x09, 0x53, 0x74, 0x61, 
0x74, 0x46, 0x73, 0x52,
+       0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 
0x20, 0x01, 0x28, 0x09,
+       0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x43, 0x6f, 
0x6e, 0x74, 0x65, 0x78,
+       0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 
0x2e, 0x52, 0x50, 0x43,
+       0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x43, 0x6f, 0x6e, 
0x74, 0x65, 0x78, 0x74,
+       0x22, 0x4b, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 
0x52, 0x65, 0x71, 0x12,
+       0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 
0x09, 0x52, 0x04, 0x4e,
+       0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 
0x78, 0x74, 0x18, 0x02,
+       0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 
0x43, 0x43, 0x6f, 0x6e,
+       0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 
0x74, 0x22, 0x4a, 0x0a,
+       0x0a, 0x4f, 0x70, 0x65, 0x6e, 0x44, 0x69, 0x72, 0x52, 0x65, 0x71, 0x12, 
0x12, 0x0a, 0x04, 0x4e,
+       0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 
0x61, 0x6d, 0x65, 0x12,
+       0x28, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 
0x20, 0x01, 0x28, 0x0b,
+       0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x43, 0x6f, 0x6e, 
0x74, 0x65, 0x78, 0x74,
+       0x52, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x4b, 0x0a, 
0x0b, 0x4f, 0x70, 0x65,
+       0x6e, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 
0x4e, 0x61, 0x6d, 0x65,
+       0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 
0x12, 0x28, 0x0a, 0x07,
+       0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 
0x0b, 0x32, 0x0e, 0x2e,
+       0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 
0x74, 0x52, 0x07, 0x43,
+       0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x4a, 0x0a, 0x0a, 0x52, 0x65, 
0x61, 0x64, 0x44, 0x69,
+       0x72, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 
0x18, 0x01, 0x20, 0x01,
+       0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x07, 
0x43, 0x6f, 0x6e, 0x74,
+       0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 
0x70, 0x62, 0x2e, 0x52,
+       0x50, 0x43, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x43, 
0x6f, 0x6e, 0x74, 0x65,
+       0x78, 0x74, 0x22, 0x4b, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x46, 0x69, 
0x6c, 0x65, 0x52, 0x65,
+       0x71, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 
0x01, 0x28, 0x09, 0x52,
+       0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 
0x74, 0x65, 0x78, 0x74,
+       0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 
0x52, 0x50, 0x43, 0x43,
+       0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x43, 0x6f, 0x6e, 0x74, 
0x65, 0x78, 0x74, 0x22,
+       0x78, 0x0a, 0x0c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 
0x52, 0x65, 0x71, 0x12,
+       0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 
0x09, 0x52, 0x04, 0x4e,
+       0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 
0x78, 0x74, 0x18, 0x02,
+       0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 
0x43, 0x43, 0x6f, 0x6e,
+       0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 
0x74, 0x12, 0x12, 0x0a,
+       0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 
0x04, 0x44, 0x61, 0x74,
+       0x61, 0x12, 0x16, 0x0a, 0x06, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 
0x04, 0x20, 0x01, 0x28,
+       0x03, 0x52, 0x06, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0xa0, 0x02, 
0x0a, 0x0e, 0x53, 0x65,
+       0x74, 0x49, 0x6e, 0x6f, 0x64, 0x65, 0x41, 0x74, 0x74, 0x52, 0x65, 0x71, 
0x12, 0x12, 0x0a, 0x04,
+       0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 
0x4e, 0x61, 0x6d, 0x65,
+       0x12, 0x28, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 
0x02, 0x20, 0x01, 0x28,
+       0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x43, 0x43, 0x6f, 
0x6e, 0x74, 0x65, 0x78,
+       0x74, 0x52, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x17, 
0x0a, 0x04, 0x53, 0x69,
+       0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x04, 
0x53, 0x69, 0x7a, 0x65,
+       0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x4d, 
0x6f, 0x64, 0x65, 0x18,
+       0x04, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x01, 0x52, 0x08, 0x46, 0x69, 0x6c, 
0x65, 0x4d, 0x6f, 0x64,
+       0x65, 0x88, 0x01, 0x01, 0x12, 0x35, 0x0a, 0x05, 0x41, 0x54, 0x69, 0x6d, 
0x65, 0x18, 0x05, 0x20,
+       0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 
0x2e, 0x70, 0x72, 0x6f,
+       0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 
0x61, 0x6d, 0x70, 0x48,
+       0x02, 0x52, 0x05, 0x41, 0x54, 0x69, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 
0x35, 0x0a, 0x05, 0x4d,
+       0x54, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 
0x2e, 0x67, 0x6f, 0x6f,
+       0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 
0x2e, 0x54, 0x69, 0x6d,
+       0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, 0x03, 0x52, 0x05, 0x4d, 0x54, 
0x69, 0x6d, 0x65, 0x88,
+       0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x53, 0x69, 0x7a, 0x65, 0x42, 
0x0b, 0x0a, 0x09, 0x5f,
+       0x46, 0x69, 0x6c, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x42, 0x08, 0x0a, 0x06, 
0x5f, 0x41, 0x54, 0x69,
+       0x6d, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x4d, 0x54, 0x69, 0x6d, 0x65, 
0x22, 0x2f, 0x0a, 0x09,
+       0x53, 0x74, 0x61, 0x74, 0x46, 0x73, 0x52, 0x65, 0x73, 0x12, 0x22, 0x0a, 
0x06, 0x52, 0x65, 0x73,
+       0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 
0x70, 0x62, 0x2e, 0x53,
+       0x74, 0x61, 0x74, 0x46, 0x73, 0x52, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 
0x74, 0x22, 0x33, 0x0a,
+       0x0b, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 
0x12, 0x24, 0x0a, 0x06,
+       0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 
0x32, 0x0c, 0x2e, 0x70,
+       0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 
0x52, 0x65, 0x73, 0x75,
+       0x6c, 0x74, 0x22, 0x33, 0x0a, 0x0a, 0x4f, 0x70, 0x65, 0x6e, 0x44, 0x69, 
0x72, 0x52, 0x65, 0x73,
+       0x12, 0x25, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 
0x20, 0x01, 0x28, 0x0b,
+       0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x65, 0x64, 
0x44, 0x69, 0x72, 0x52,
+       0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x35, 0x0a, 0x0b, 0x4f, 
0x70, 0x65, 0x6e, 0x46,
+       0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x06, 0x52, 0x65, 
0x73, 0x75, 0x6c, 0x74,
+       0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 
0x4f, 0x70, 0x65, 0x6e,
+       0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x06, 0x52, 0x65, 0x73, 0x75, 
0x6c, 0x74, 0x22, 0x32,
+       0x0a, 0x0a, 0x52, 0x65, 0x61, 0x64, 0x44, 0x69, 0x72, 0x52, 0x65, 0x73, 
0x12, 0x24, 0x0a, 0x06,
+       0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 
0x32, 0x0c, 0x2e, 0x70,
+       0x62, 0x2e, 0x44, 0x69, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 
0x52, 0x65, 0x73, 0x75,
+       0x6c, 0x74, 0x22, 0x34, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x46, 0x69, 
0x6c, 0x65, 0x52, 0x65,
+       0x73, 0x12, 0x25, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 
0x01, 0x20, 0x01, 0x28,
+       0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x45, 
0x6e, 0x74, 0x72, 0x79,
+       0x52, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x26, 0x0a, 0x0c, 
0x57, 0x72, 0x69, 0x74,
+       0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 
0x52, 0x65, 0x73, 0x75,
+       0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x52, 0x65, 
0x73, 0x75, 0x6c, 0x74,
+       0x22, 0x36, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x6f, 0x64, 0x65, 
0x41, 0x74, 0x74, 0x52,
+       0x65, 0x73, 0x12, 0x24, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 
0x18, 0x01, 0x20, 0x01,
+       0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x49, 0x6e, 0x6f, 0x64, 
0x65, 0x41, 0x74, 0x74,
+       0x52, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0x8d, 0x03, 0x0a, 
0x0b, 0x46, 0x75, 0x73,
+       0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x28, 0x0a, 0x06, 
0x53, 0x74, 0x61, 0x74,
+       0x46, 0x73, 0x12, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 
0x46, 0x73, 0x52, 0x65,
+       0x71, 0x1a, 0x0d, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x46, 
0x73, 0x52, 0x65, 0x73,
+       0x22, 0x00, 0x12, 0x2e, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 
0x66, 0x6f, 0x12, 0x0f,
+       0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 
0x52, 0x65, 0x71, 0x1a,
+       0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 
0x6f, 0x52, 0x65, 0x73,
+       0x22, 0x00, 0x12, 0x2b, 0x0a, 0x07, 0x4f, 0x70, 0x65, 0x6e, 0x44, 0x69, 
0x72, 0x12, 0x0e, 0x2e,
+       0x70, 0x62, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x44, 0x69, 0x72, 0x52, 0x65, 
0x71, 0x1a, 0x0e, 0x2e,
+       0x70, 0x62, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x44, 0x69, 0x72, 0x52, 0x65, 
0x73, 0x22, 0x00, 0x12,
+       0x2e, 0x0a, 0x08, 0x4f, 0x70, 0x65, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x12, 
0x0f, 0x2e, 0x70, 0x62,
+       0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 
0x1a, 0x0f, 0x2e, 0x70,
+       0x62, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 
0x73, 0x22, 0x00, 0x12,
+       0x2b, 0x0a, 0x07, 0x52, 0x65, 0x61, 0x64, 0x44, 0x69, 0x72, 0x12, 0x0e, 
0x2e, 0x70, 0x62, 0x2e,
+       0x52, 0x65, 0x61, 0x64, 0x44, 0x69, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x0e, 
0x2e, 0x70, 0x62, 0x2e,
+       0x52, 0x65, 0x61, 0x64, 0x44, 0x69, 0x72, 0x52, 0x65, 0x73, 0x22, 0x00, 
0x12, 0x2e, 0x0a, 0x08,
+       0x52, 0x65, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x0f, 0x2e, 0x70, 
0x62, 0x2e, 0x52, 0x65,
+       0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 
0x70, 0x62, 0x2e, 0x52,
+       0x65, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x22, 0x00, 
0x12, 0x31, 0x0a, 0x09,
+       0x57, 0x72, 0x69, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x10, 0x2e, 
0x70, 0x62, 0x2e, 0x57,
+       0x72, 0x69, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x1a, 
0x10, 0x2e, 0x70, 0x62,
+       0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 
0x73, 0x22, 0x00, 0x12,
+       0x37, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x6f, 0x64, 0x65, 0x41, 
0x74, 0x74, 0x12, 0x12,
+       0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x6f, 0x64, 0x65, 
0x41, 0x74, 0x74, 0x52,
+       0x65, 0x71, 0x1a, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x74, 0x49, 
0x6e, 0x6f, 0x64, 0x65,
+       0x41, 0x74, 0x74, 0x52, 0x65, 0x73, 0x22, 0x00, 0x42, 0x0b, 0x5a, 0x09, 
0x67, 0x72, 0x70, 0x63,
+       0x66, 0x73, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 
0x33,
+}
+
+var (
+       file_proto_grpcfs_proto_rawDescOnce sync.Once
+       file_proto_grpcfs_proto_rawDescData = file_proto_grpcfs_proto_rawDesc
+)
+
+func file_proto_grpcfs_proto_rawDescGZIP() []byte {
+       file_proto_grpcfs_proto_rawDescOnce.Do(func() {
+               file_proto_grpcfs_proto_rawDescData = 
protoimpl.X.CompressGZIP(file_proto_grpcfs_proto_rawDescData)
+       })
+       return file_proto_grpcfs_proto_rawDescData
+}
+
+var file_proto_grpcfs_proto_msgTypes = make([]protoimpl.MessageInfo, 25)
+var file_proto_grpcfs_proto_goTypes = []any{
+       (*RPCContext)(nil),            // 0: pb.RPCContext
+       (*OpContext)(nil),             // 1: pb.OpContext
+       (*StatFs)(nil),                // 2: pb.StatFs
+       (*FileInfo)(nil),              // 3: pb.FileInfo
+       (*OpenedDir)(nil),             // 4: pb.OpenedDir
+       (*OpenedFile)(nil),            // 5: pb.OpenedFile
+       (*DirEntry)(nil),              // 6: pb.DirEntry
+       (*FileEntry)(nil),             // 7: pb.FileEntry
+       (*InodeAtt)(nil),              // 8: pb.InodeAtt
+       (*StatFsReq)(nil),             // 9: pb.StatFsReq
+       (*FileInfoReq)(nil),           // 10: pb.FileInfoReq
+       (*OpenDirReq)(nil),            // 11: pb.OpenDirReq
+       (*OpenFileReq)(nil),           // 12: pb.OpenFileReq
+       (*ReadDirReq)(nil),            // 13: pb.ReadDirReq
+       (*ReadFileReq)(nil),           // 14: pb.ReadFileReq
+       (*WriteFileReq)(nil),          // 15: pb.WriteFileReq
+       (*SetInodeAttReq)(nil),        // 16: pb.SetInodeAttReq
+       (*StatFsRes)(nil),             // 17: pb.StatFsRes
+       (*FileInfoRes)(nil),           // 18: pb.FileInfoRes
+       (*OpenDirRes)(nil),            // 19: pb.OpenDirRes
+       (*OpenFileRes)(nil),           // 20: pb.OpenFileRes
+       (*ReadDirRes)(nil),            // 21: pb.ReadDirRes
+       (*ReadFileRes)(nil),           // 22: pb.ReadFileRes
+       (*WriteFileRes)(nil),          // 23: pb.WriteFileRes
+       (*SetInodeAttRes)(nil),        // 24: pb.SetInodeAttRes
+       (*timestamppb.Timestamp)(nil), // 25: google.protobuf.Timestamp
+}
+var file_proto_grpcfs_proto_depIdxs = []int32{
+       25, // 0: pb.FileInfo.ModTime:type_name -> google.protobuf.Timestamp
+       1,  // 1: pb.OpenedDir.OpContext:type_name -> pb.OpContext
+       1,  // 2: pb.OpenedFile.OpContext:type_name -> pb.OpContext
+       3,  // 3: pb.DirEntry.Info:type_name -> pb.FileInfo
+       1,  // 4: pb.FileEntry.OpContext:type_name -> pb.OpContext
+       25, // 5: pb.InodeAtt.Atime:type_name -> google.protobuf.Timestamp
+       25, // 6: pb.InodeAtt.Mtime:type_name -> google.protobuf.Timestamp
+       25, // 7: pb.InodeAtt.Ctime:type_name -> google.protobuf.Timestamp
+       0,  // 8: pb.StatFsReq.Context:type_name -> pb.RPCContext
+       0,  // 9: pb.FileInfoReq.Context:type_name -> pb.RPCContext
+       0,  // 10: pb.OpenDirReq.Context:type_name -> pb.RPCContext
+       0,  // 11: pb.OpenFileReq.Context:type_name -> pb.RPCContext
+       0,  // 12: pb.ReadDirReq.Context:type_name -> pb.RPCContext
+       0,  // 13: pb.ReadFileReq.Context:type_name -> pb.RPCContext
+       0,  // 14: pb.WriteFileReq.Context:type_name -> pb.RPCContext
+       0,  // 15: pb.SetInodeAttReq.Context:type_name -> pb.RPCContext
+       25, // 16: pb.SetInodeAttReq.ATime:type_name -> 
google.protobuf.Timestamp
+       25, // 17: pb.SetInodeAttReq.MTime:type_name -> 
google.protobuf.Timestamp
+       2,  // 18: pb.StatFsRes.Result:type_name -> pb.StatFs
+       3,  // 19: pb.FileInfoRes.Result:type_name -> pb.FileInfo
+       4,  // 20: pb.OpenDirRes.Result:type_name -> pb.OpenedDir
+       5,  // 21: pb.OpenFileRes.Result:type_name -> pb.OpenedFile
+       6,  // 22: pb.ReadDirRes.Result:type_name -> pb.DirEntry
+       7,  // 23: pb.ReadFileRes.Result:type_name -> pb.FileEntry
+       8,  // 24: pb.SetInodeAttRes.Result:type_name -> pb.InodeAtt
+       9,  // 25: pb.FuseService.StatFs:input_type -> pb.StatFsReq
+       10, // 26: pb.FuseService.FileInfo:input_type -> pb.FileInfoReq
+       11, // 27: pb.FuseService.OpenDir:input_type -> pb.OpenDirReq
+       12, // 28: pb.FuseService.OpenFile:input_type -> pb.OpenFileReq
+       13, // 29: pb.FuseService.ReadDir:input_type -> pb.ReadDirReq
+       14, // 30: pb.FuseService.ReadFile:input_type -> pb.ReadFileReq
+       15, // 31: pb.FuseService.WriteFile:input_type -> pb.WriteFileReq
+       16, // 32: pb.FuseService.SetInodeAtt:input_type -> pb.SetInodeAttReq
+       17, // 33: pb.FuseService.StatFs:output_type -> pb.StatFsRes
+       18, // 34: pb.FuseService.FileInfo:output_type -> pb.FileInfoRes
+       19, // 35: pb.FuseService.OpenDir:output_type -> pb.OpenDirRes
+       20, // 36: pb.FuseService.OpenFile:output_type -> pb.OpenFileRes
+       21, // 37: pb.FuseService.ReadDir:output_type -> pb.ReadDirRes
+       22, // 38: pb.FuseService.ReadFile:output_type -> pb.ReadFileRes
+       23, // 39: pb.FuseService.WriteFile:output_type -> pb.WriteFileRes
+       24, // 40: pb.FuseService.SetInodeAtt:output_type -> pb.SetInodeAttRes
+       33, // [33:41] is the sub-list for method output_type
+       25, // [25:33] is the sub-list for method input_type
+       25, // [25:25] is the sub-list for extension type_name
+       25, // [25:25] is the sub-list for extension extendee
+       0,  // [0:25] is the sub-list for field type_name
+}
+
+func init() { file_proto_grpcfs_proto_init() }
+func file_proto_grpcfs_proto_init() {
+       if File_proto_grpcfs_proto != nil {
+               return
+       }
+       if !protoimpl.UnsafeEnabled {
+               file_proto_grpcfs_proto_msgTypes[0].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*RPCContext); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[1].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*OpContext); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[2].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*StatFs); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[3].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*FileInfo); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[4].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*OpenedDir); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[5].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*OpenedFile); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[6].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*DirEntry); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[7].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*FileEntry); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[8].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*InodeAtt); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[9].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*StatFsReq); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[10].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*FileInfoReq); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[11].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*OpenDirReq); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[12].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*OpenFileReq); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[13].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*ReadDirReq); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[14].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*ReadFileReq); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[15].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*WriteFileReq); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[16].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*SetInodeAttReq); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[17].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*StatFsRes); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[18].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*FileInfoRes); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[19].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*OpenDirRes); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[20].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*OpenFileRes); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[21].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*ReadDirRes); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[22].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*ReadFileRes); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[23].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*WriteFileRes); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_grpcfs_proto_msgTypes[24].Exporter = func(v any, i 
int) any {
+                       switch v := v.(*SetInodeAttRes); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+       }
+       file_proto_grpcfs_proto_msgTypes[16].OneofWrappers = []any{}
+       type x struct{}
+       out := protoimpl.TypeBuilder{
+               File: protoimpl.DescBuilder{
+                       GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+                       RawDescriptor: file_proto_grpcfs_proto_rawDesc,
+                       NumEnums:      0,
+                       NumMessages:   25,
+                       NumExtensions: 0,
+                       NumServices:   1,
+               },
+               GoTypes:           file_proto_grpcfs_proto_goTypes,
+               DependencyIndexes: file_proto_grpcfs_proto_depIdxs,
+               MessageInfos:      file_proto_grpcfs_proto_msgTypes,
+       }.Build()
+       File_proto_grpcfs_proto = out.File
+       file_proto_grpcfs_proto_rawDesc = nil
+       file_proto_grpcfs_proto_goTypes = nil
+       file_proto_grpcfs_proto_depIdxs = nil
+}
diff --git 
a/modules/agent-framework/airavata-fuse/src/grpcfs/pb/grpcfs_grpc.pb.go 
b/modules/agent-framework/airavata-fuse/src/grpcfs/pb/grpcfs_grpc.pb.go
new file mode 100644
index 0000000000..894a1cfd12
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs/pb/grpcfs_grpc.pb.go
@@ -0,0 +1,380 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.4.0
+// - protoc             v5.27.1
+// source: proto/grpcfs.proto
+
+package pb
+
+import (
+       context "context"
+       grpc "google.golang.org/grpc"
+       codes "google.golang.org/grpc/codes"
+       status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.62.0 or later.
+const _ = grpc.SupportPackageIsVersion8
+
+const (
+       FuseService_StatFs_FullMethodName      = "/pb.FuseService/StatFs"
+       FuseService_FileInfo_FullMethodName    = "/pb.FuseService/FileInfo"
+       FuseService_OpenDir_FullMethodName     = "/pb.FuseService/OpenDir"
+       FuseService_OpenFile_FullMethodName    = "/pb.FuseService/OpenFile"
+       FuseService_ReadDir_FullMethodName     = "/pb.FuseService/ReadDir"
+       FuseService_ReadFile_FullMethodName    = "/pb.FuseService/ReadFile"
+       FuseService_WriteFile_FullMethodName   = "/pb.FuseService/WriteFile"
+       FuseService_SetInodeAtt_FullMethodName = "/pb.FuseService/SetInodeAtt"
+)
+
+// FuseServiceClient is the client API for FuseService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please 
refer to 
https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+//
+// Service Definition
+type FuseServiceClient interface {
+       StatFs(ctx context.Context, in *StatFsReq, opts ...grpc.CallOption) 
(*StatFsRes, error)
+       FileInfo(ctx context.Context, in *FileInfoReq, opts ...grpc.CallOption) 
(*FileInfoRes, error)
+       OpenDir(ctx context.Context, in *OpenDirReq, opts ...grpc.CallOption) 
(*OpenDirRes, error)
+       OpenFile(ctx context.Context, in *OpenFileReq, opts ...grpc.CallOption) 
(*OpenFileRes, error)
+       ReadDir(ctx context.Context, in *ReadDirReq, opts ...grpc.CallOption) 
(*ReadDirRes, error)
+       ReadFile(ctx context.Context, in *ReadFileReq, opts ...grpc.CallOption) 
(*ReadFileRes, error)
+       WriteFile(ctx context.Context, in *WriteFileReq, opts 
...grpc.CallOption) (*WriteFileRes, error)
+       SetInodeAtt(ctx context.Context, in *SetInodeAttReq, opts 
...grpc.CallOption) (*SetInodeAttRes, error)
+}
+
+type fuseServiceClient struct {
+       cc grpc.ClientConnInterface
+}
+
+func NewFuseServiceClient(cc grpc.ClientConnInterface) FuseServiceClient {
+       return &fuseServiceClient{cc}
+}
+
+func (c *fuseServiceClient) StatFs(ctx context.Context, in *StatFsReq, opts 
...grpc.CallOption) (*StatFsRes, error) {
+       cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+       out := new(StatFsRes)
+       err := c.cc.Invoke(ctx, FuseService_StatFs_FullMethodName, in, out, 
cOpts...)
+       if err != nil {
+               return nil, err
+       }
+       return out, nil
+}
+
+func (c *fuseServiceClient) FileInfo(ctx context.Context, in *FileInfoReq, 
opts ...grpc.CallOption) (*FileInfoRes, error) {
+       cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+       out := new(FileInfoRes)
+       err := c.cc.Invoke(ctx, FuseService_FileInfo_FullMethodName, in, out, 
cOpts...)
+       if err != nil {
+               return nil, err
+       }
+       return out, nil
+}
+
+func (c *fuseServiceClient) OpenDir(ctx context.Context, in *OpenDirReq, opts 
...grpc.CallOption) (*OpenDirRes, error) {
+       cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+       out := new(OpenDirRes)
+       err := c.cc.Invoke(ctx, FuseService_OpenDir_FullMethodName, in, out, 
cOpts...)
+       if err != nil {
+               return nil, err
+       }
+       return out, nil
+}
+
+func (c *fuseServiceClient) OpenFile(ctx context.Context, in *OpenFileReq, 
opts ...grpc.CallOption) (*OpenFileRes, error) {
+       cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+       out := new(OpenFileRes)
+       err := c.cc.Invoke(ctx, FuseService_OpenFile_FullMethodName, in, out, 
cOpts...)
+       if err != nil {
+               return nil, err
+       }
+       return out, nil
+}
+
+func (c *fuseServiceClient) ReadDir(ctx context.Context, in *ReadDirReq, opts 
...grpc.CallOption) (*ReadDirRes, error) {
+       cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+       out := new(ReadDirRes)
+       err := c.cc.Invoke(ctx, FuseService_ReadDir_FullMethodName, in, out, 
cOpts...)
+       if err != nil {
+               return nil, err
+       }
+       return out, nil
+}
+
+func (c *fuseServiceClient) ReadFile(ctx context.Context, in *ReadFileReq, 
opts ...grpc.CallOption) (*ReadFileRes, error) {
+       cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+       out := new(ReadFileRes)
+       err := c.cc.Invoke(ctx, FuseService_ReadFile_FullMethodName, in, out, 
cOpts...)
+       if err != nil {
+               return nil, err
+       }
+       return out, nil
+}
+
+func (c *fuseServiceClient) WriteFile(ctx context.Context, in *WriteFileReq, 
opts ...grpc.CallOption) (*WriteFileRes, error) {
+       cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+       out := new(WriteFileRes)
+       err := c.cc.Invoke(ctx, FuseService_WriteFile_FullMethodName, in, out, 
cOpts...)
+       if err != nil {
+               return nil, err
+       }
+       return out, nil
+}
+
+func (c *fuseServiceClient) SetInodeAtt(ctx context.Context, in 
*SetInodeAttReq, opts ...grpc.CallOption) (*SetInodeAttRes, error) {
+       cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+       out := new(SetInodeAttRes)
+       err := c.cc.Invoke(ctx, FuseService_SetInodeAtt_FullMethodName, in, 
out, cOpts...)
+       if err != nil {
+               return nil, err
+       }
+       return out, nil
+}
+
+// FuseServiceServer is the server API for FuseService service.
+// All implementations must embed UnimplementedFuseServiceServer
+// for forward compatibility
+//
+// Service Definition
+type FuseServiceServer interface {
+       StatFs(context.Context, *StatFsReq) (*StatFsRes, error)
+       FileInfo(context.Context, *FileInfoReq) (*FileInfoRes, error)
+       OpenDir(context.Context, *OpenDirReq) (*OpenDirRes, error)
+       OpenFile(context.Context, *OpenFileReq) (*OpenFileRes, error)
+       ReadDir(context.Context, *ReadDirReq) (*ReadDirRes, error)
+       ReadFile(context.Context, *ReadFileReq) (*ReadFileRes, error)
+       WriteFile(context.Context, *WriteFileReq) (*WriteFileRes, error)
+       SetInodeAtt(context.Context, *SetInodeAttReq) (*SetInodeAttRes, error)
+       mustEmbedUnimplementedFuseServiceServer()
+}
+
+// UnimplementedFuseServiceServer must be embedded to have forward compatible 
implementations.
+type UnimplementedFuseServiceServer struct {
+}
+
+func (UnimplementedFuseServiceServer) StatFs(context.Context, *StatFsReq) 
(*StatFsRes, error) {
+       return nil, status.Errorf(codes.Unimplemented, "method StatFs not 
implemented")
+}
+func (UnimplementedFuseServiceServer) FileInfo(context.Context, *FileInfoReq) 
(*FileInfoRes, error) {
+       return nil, status.Errorf(codes.Unimplemented, "method FileInfo not 
implemented")
+}
+func (UnimplementedFuseServiceServer) OpenDir(context.Context, *OpenDirReq) 
(*OpenDirRes, error) {
+       return nil, status.Errorf(codes.Unimplemented, "method OpenDir not 
implemented")
+}
+func (UnimplementedFuseServiceServer) OpenFile(context.Context, *OpenFileReq) 
(*OpenFileRes, error) {
+       return nil, status.Errorf(codes.Unimplemented, "method OpenFile not 
implemented")
+}
+func (UnimplementedFuseServiceServer) ReadDir(context.Context, *ReadDirReq) 
(*ReadDirRes, error) {
+       return nil, status.Errorf(codes.Unimplemented, "method ReadDir not 
implemented")
+}
+func (UnimplementedFuseServiceServer) ReadFile(context.Context, *ReadFileReq) 
(*ReadFileRes, error) {
+       return nil, status.Errorf(codes.Unimplemented, "method ReadFile not 
implemented")
+}
+func (UnimplementedFuseServiceServer) WriteFile(context.Context, 
*WriteFileReq) (*WriteFileRes, error) {
+       return nil, status.Errorf(codes.Unimplemented, "method WriteFile not 
implemented")
+}
+func (UnimplementedFuseServiceServer) SetInodeAtt(context.Context, 
*SetInodeAttReq) (*SetInodeAttRes, error) {
+       return nil, status.Errorf(codes.Unimplemented, "method SetInodeAtt not 
implemented")
+}
+func (UnimplementedFuseServiceServer) 
mustEmbedUnimplementedFuseServiceServer() {}
+
+// UnsafeFuseServiceServer may be embedded to opt out of forward compatibility 
for this service.
+// Use of this interface is not recommended, as added methods to 
FuseServiceServer will
+// result in compilation errors.
+type UnsafeFuseServiceServer interface {
+       mustEmbedUnimplementedFuseServiceServer()
+}
+
+func RegisterFuseServiceServer(s grpc.ServiceRegistrar, srv FuseServiceServer) 
{
+       s.RegisterService(&FuseService_ServiceDesc, srv)
+}
+
+func _FuseService_StatFs_Handler(srv interface{}, ctx context.Context, dec 
func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, 
error) {
+       in := new(StatFsReq)
+       if err := dec(in); err != nil {
+               return nil, err
+       }
+       if interceptor == nil {
+               return srv.(FuseServiceServer).StatFs(ctx, in)
+       }
+       info := &grpc.UnaryServerInfo{
+               Server:     srv,
+               FullMethod: FuseService_StatFs_FullMethodName,
+       }
+       handler := func(ctx context.Context, req interface{}) (interface{}, 
error) {
+               return srv.(FuseServiceServer).StatFs(ctx, req.(*StatFsReq))
+       }
+       return interceptor(ctx, in, info, handler)
+}
+
+func _FuseService_FileInfo_Handler(srv interface{}, ctx context.Context, dec 
func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, 
error) {
+       in := new(FileInfoReq)
+       if err := dec(in); err != nil {
+               return nil, err
+       }
+       if interceptor == nil {
+               return srv.(FuseServiceServer).FileInfo(ctx, in)
+       }
+       info := &grpc.UnaryServerInfo{
+               Server:     srv,
+               FullMethod: FuseService_FileInfo_FullMethodName,
+       }
+       handler := func(ctx context.Context, req interface{}) (interface{}, 
error) {
+               return srv.(FuseServiceServer).FileInfo(ctx, req.(*FileInfoReq))
+       }
+       return interceptor(ctx, in, info, handler)
+}
+
+func _FuseService_OpenDir_Handler(srv interface{}, ctx context.Context, dec 
func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, 
error) {
+       in := new(OpenDirReq)
+       if err := dec(in); err != nil {
+               return nil, err
+       }
+       if interceptor == nil {
+               return srv.(FuseServiceServer).OpenDir(ctx, in)
+       }
+       info := &grpc.UnaryServerInfo{
+               Server:     srv,
+               FullMethod: FuseService_OpenDir_FullMethodName,
+       }
+       handler := func(ctx context.Context, req interface{}) (interface{}, 
error) {
+               return srv.(FuseServiceServer).OpenDir(ctx, req.(*OpenDirReq))
+       }
+       return interceptor(ctx, in, info, handler)
+}
+
+func _FuseService_OpenFile_Handler(srv interface{}, ctx context.Context, dec 
func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, 
error) {
+       in := new(OpenFileReq)
+       if err := dec(in); err != nil {
+               return nil, err
+       }
+       if interceptor == nil {
+               return srv.(FuseServiceServer).OpenFile(ctx, in)
+       }
+       info := &grpc.UnaryServerInfo{
+               Server:     srv,
+               FullMethod: FuseService_OpenFile_FullMethodName,
+       }
+       handler := func(ctx context.Context, req interface{}) (interface{}, 
error) {
+               return srv.(FuseServiceServer).OpenFile(ctx, req.(*OpenFileReq))
+       }
+       return interceptor(ctx, in, info, handler)
+}
+
+func _FuseService_ReadDir_Handler(srv interface{}, ctx context.Context, dec 
func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, 
error) {
+       in := new(ReadDirReq)
+       if err := dec(in); err != nil {
+               return nil, err
+       }
+       if interceptor == nil {
+               return srv.(FuseServiceServer).ReadDir(ctx, in)
+       }
+       info := &grpc.UnaryServerInfo{
+               Server:     srv,
+               FullMethod: FuseService_ReadDir_FullMethodName,
+       }
+       handler := func(ctx context.Context, req interface{}) (interface{}, 
error) {
+               return srv.(FuseServiceServer).ReadDir(ctx, req.(*ReadDirReq))
+       }
+       return interceptor(ctx, in, info, handler)
+}
+
+func _FuseService_ReadFile_Handler(srv interface{}, ctx context.Context, dec 
func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, 
error) {
+       in := new(ReadFileReq)
+       if err := dec(in); err != nil {
+               return nil, err
+       }
+       if interceptor == nil {
+               return srv.(FuseServiceServer).ReadFile(ctx, in)
+       }
+       info := &grpc.UnaryServerInfo{
+               Server:     srv,
+               FullMethod: FuseService_ReadFile_FullMethodName,
+       }
+       handler := func(ctx context.Context, req interface{}) (interface{}, 
error) {
+               return srv.(FuseServiceServer).ReadFile(ctx, req.(*ReadFileReq))
+       }
+       return interceptor(ctx, in, info, handler)
+}
+
+func _FuseService_WriteFile_Handler(srv interface{}, ctx context.Context, dec 
func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, 
error) {
+       in := new(WriteFileReq)
+       if err := dec(in); err != nil {
+               return nil, err
+       }
+       if interceptor == nil {
+               return srv.(FuseServiceServer).WriteFile(ctx, in)
+       }
+       info := &grpc.UnaryServerInfo{
+               Server:     srv,
+               FullMethod: FuseService_WriteFile_FullMethodName,
+       }
+       handler := func(ctx context.Context, req interface{}) (interface{}, 
error) {
+               return srv.(FuseServiceServer).WriteFile(ctx, 
req.(*WriteFileReq))
+       }
+       return interceptor(ctx, in, info, handler)
+}
+
+func _FuseService_SetInodeAtt_Handler(srv interface{}, ctx context.Context, 
dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) 
(interface{}, error) {
+       in := new(SetInodeAttReq)
+       if err := dec(in); err != nil {
+               return nil, err
+       }
+       if interceptor == nil {
+               return srv.(FuseServiceServer).SetInodeAtt(ctx, in)
+       }
+       info := &grpc.UnaryServerInfo{
+               Server:     srv,
+               FullMethod: FuseService_SetInodeAtt_FullMethodName,
+       }
+       handler := func(ctx context.Context, req interface{}) (interface{}, 
error) {
+               return srv.(FuseServiceServer).SetInodeAtt(ctx, 
req.(*SetInodeAttReq))
+       }
+       return interceptor(ctx, in, info, handler)
+}
+
+// FuseService_ServiceDesc is the grpc.ServiceDesc for FuseService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var FuseService_ServiceDesc = grpc.ServiceDesc{
+       ServiceName: "pb.FuseService",
+       HandlerType: (*FuseServiceServer)(nil),
+       Methods: []grpc.MethodDesc{
+               {
+                       MethodName: "StatFs",
+                       Handler:    _FuseService_StatFs_Handler,
+               },
+               {
+                       MethodName: "FileInfo",
+                       Handler:    _FuseService_FileInfo_Handler,
+               },
+               {
+                       MethodName: "OpenDir",
+                       Handler:    _FuseService_OpenDir_Handler,
+               },
+               {
+                       MethodName: "OpenFile",
+                       Handler:    _FuseService_OpenFile_Handler,
+               },
+               {
+                       MethodName: "ReadDir",
+                       Handler:    _FuseService_ReadDir_Handler,
+               },
+               {
+                       MethodName: "ReadFile",
+                       Handler:    _FuseService_ReadFile_Handler,
+               },
+               {
+                       MethodName: "WriteFile",
+                       Handler:    _FuseService_WriteFile_Handler,
+               },
+               {
+                       MethodName: "SetInodeAtt",
+                       Handler:    _FuseService_SetInodeAtt_Handler,
+               },
+       },
+       Streams:  []grpc.StreamDesc{},
+       Metadata: "proto/grpcfs.proto",
+}
diff --git a/modules/agent-framework/airavata-fuse/src/grpcfs_client/go.mod 
b/modules/agent-framework/airavata-fuse/src/grpcfs_client/go.mod
new file mode 100644
index 0000000000..a200afac0e
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs_client/go.mod
@@ -0,0 +1,19 @@
+module client
+
+go 1.22.5
+
+replace grpcfs => ../grpcfs
+
+require (
+       github.com/jacobsa/fuse v0.0.0-20240626143436-8a36813dc074
+       grpcfs v0.0.0-00010101000000-000000000000
+)
+
+require (
+       golang.org/x/net v0.25.0 // indirect
+       golang.org/x/sys v0.22.0 // indirect
+       golang.org/x/text v0.15.0 // indirect
+       google.golang.org/genproto/googleapis/rpc 
v0.0.0-20240528184218-531527333157 // indirect
+       google.golang.org/grpc v1.65.0 // indirect
+       google.golang.org/protobuf v1.34.2 // indirect
+)
diff --git a/modules/agent-framework/airavata-fuse/src/grpcfs_client/go.sum 
b/modules/agent-framework/airavata-fuse/src/grpcfs_client/go.sum
new file mode 100644
index 0000000000..c870a6e897
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs_client/go.sum
@@ -0,0 +1,18 @@
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod 
h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/jacobsa/fuse v0.0.0-20240626143436-8a36813dc074 
h1:rrmTkL654m7vQTYzi9NpEzAO7t0to5f1/jgkvSorVs8=
+github.com/jacobsa/fuse v0.0.0-20240626143436-8a36813dc074/go.mod 
h1:JYi9iIxdYNgxmMgLwtSHO/hmVnP2kfX1oc+mtx+XWLA=
+github.com/kylelemons/godebug v1.1.0 
h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod 
h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
+golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
+golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod 
h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 
h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
+google.golang.org/genproto/googleapis/rpc 
v0.0.0-20240528184218-531527333157/go.mod 
h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
+google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
+google.golang.org/grpc v1.65.0/go.mod 
h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
+google.golang.org/protobuf v1.34.2 
h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
+google.golang.org/protobuf v1.34.2/go.mod 
h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
diff --git a/modules/agent-framework/airavata-fuse/src/grpcfs_client/main.go 
b/modules/agent-framework/airavata-fuse/src/grpcfs_client/main.go
new file mode 100644
index 0000000000..57d717a5ea
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs_client/main.go
@@ -0,0 +1,65 @@
+package main
+
+import (
+       "flag"
+       "log"
+       "os"
+       "os/signal"
+       "path/filepath"
+
+       "grpcfs"
+
+       "github.com/jacobsa/fuse"
+)
+
+var logger = log.Default()
+
+func handleErrIfAny(err error, message string) {
+       if err != nil {
+               logger.Fatalf("%s: %v\n", message, err)
+       }
+}
+
+func logState(message string, v ...any) {
+       logger.Print(message, v)
+}
+
+func main() {
+
+       var mountPoint string
+       var servePath string
+
+       flag.StringVar(&mountPoint, "mount", "", "Mount point")
+       flag.StringVar(&servePath, "serve", "", "Path to serve")
+       flag.Parse()
+
+       if mountPoint == "" || servePath == "" {
+               logger.Fatal("Please specify both mount point and path to 
serve")
+       }
+
+       mountPoint, err := filepath.Abs(mountPoint)
+       handleErrIfAny(err, "Invalid mount point")
+
+       server, err := grpcfs.FuseServer("127.0.0.1:50000", servePath, logger)
+       handleErrIfAny(err, "Error starting fuse server")
+
+       cfg := &fuse.MountConfig{
+               FSName:      "grpcFS",
+               Subtype:     "airavata",
+               VolumeName:  "GRPC FS - Airavata",
+               ReadOnly:    false,
+               ErrorLogger: logger,
+       }
+       mfs, err := fuse.Mount(mountPoint, server, cfg)
+       handleErrIfAny(err, "Error when mounting fs")
+
+       logState("running until interrupt", mfs)
+       sigCh := make(chan os.Signal, 1)
+       signal.Notify(sigCh, os.Interrupt)
+       <-sigCh
+       logState("interrupt received, terminating.")
+
+       if err := fuse.Unmount(mountPoint); err != nil {
+               logger.Fatalf("Unmount fail: %v\n", err)
+       }
+}
diff --git a/modules/agent-framework/airavata-fuse/src/grpcfs_server/go.mod 
b/modules/agent-framework/airavata-fuse/src/grpcfs_server/go.mod
new file mode 100644
index 0000000000..143f41402c
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs_server/go.mod
@@ -0,0 +1,18 @@
+module server
+
+go 1.22.5
+
+replace grpcfs => ../grpcfs
+
+require (
+       golang.org/x/sys v0.22.0
+       google.golang.org/grpc v1.65.0
+       google.golang.org/protobuf v1.34.2
+       grpcfs v0.0.0-00010101000000-000000000000
+)
+
+require (
+       golang.org/x/net v0.25.0 // indirect
+       golang.org/x/text v0.15.0 // indirect
+       google.golang.org/genproto/googleapis/rpc 
v0.0.0-20240528184218-531527333157 // indirect
+)
diff --git a/modules/agent-framework/airavata-fuse/src/grpcfs_server/go.sum 
b/modules/agent-framework/airavata-fuse/src/grpcfs_server/go.sum
new file mode 100644
index 0000000000..8d5b11d3de
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs_server/go.sum
@@ -0,0 +1,14 @@
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod 
h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
+golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
+golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod 
h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 
h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
+google.golang.org/genproto/googleapis/rpc 
v0.0.0-20240528184218-531527333157/go.mod 
h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
+google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
+google.golang.org/grpc v1.65.0/go.mod 
h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
+google.golang.org/protobuf v1.34.2 
h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
+google.golang.org/protobuf v1.34.2/go.mod 
h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
diff --git a/modules/agent-framework/airavata-fuse/src/grpcfs_server/main.go 
b/modules/agent-framework/airavata-fuse/src/grpcfs_server/main.go
new file mode 100644
index 0000000000..831f01416d
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/grpcfs_server/main.go
@@ -0,0 +1,222 @@
+package main
+
+import (
+       "context"
+       "grpcfs/pb"
+       "log"
+       "net"
+       "os"
+       "os/signal"
+       "syscall"
+
+       "golang.org/x/sys/unix"
+
+       "google.golang.org/grpc"
+       "google.golang.org/protobuf/types/known/timestamppb"
+)
+
+var logger = log.Default()
+
+func handleErr(err error, message string) error {
+       if err != nil {
+               logger.Printf("%s: %v\n", message, err)
+               return err
+       }
+       return nil
+}
+
+func logState(message string, v ...any) {
+       logger.Print(message, v)
+}
+
+type server struct {
+       pb.FuseServiceServer
+}
+
+func (s *server) StatFs(ctx context.Context, req *pb.StatFsReq) 
(*pb.StatFsRes, error) {
+       path := req.Name
+       rpcCtx := req.Context
+       logger.Print("received valid StatFS request. ", path, rpcCtx)
+       stat := &unix.Statfs_t{}
+       unix.Statfs(req.Name, stat)
+       res := &pb.StatFsRes{
+               Result: &pb.StatFs{
+                       BlockSize:       uint32(stat.Bsize),
+                       Blocks:          stat.Blocks,
+                       BlocksFree:      stat.Bfree,
+                       BlocksAvailable: stat.Bavail,
+                       IoSize:          uint32(stat.Bsize),
+                       InodesFree:      stat.Ffree,
+                       Inodes:          stat.Files,
+               },
+       }
+       return res, nil
+}
+
+func (s *server) FileInfo(ctx context.Context, req *pb.FileInfoReq) 
(*pb.FileInfoRes, error) {
+       path := req.Name
+       rpcCtx := req.Context
+       logger.Print("received valid FileInfo request. ", path, rpcCtx)
+       fileInfo, err := os.Stat(path)
+       if handleErr(err, "os.Stat failed") != nil {
+               return nil, err
+       }
+       stat := fileInfo.Sys().(*syscall.Stat_t)
+       res := &pb.FileInfoRes{
+               Result: &pb.FileInfo{
+                       Name:    fileInfo.Name(),
+                       Size:    fileInfo.Size(),
+                       Mode:    uint32(fileInfo.Mode()),
+                       ModTime: timestamppb.New(fileInfo.ModTime()),
+                       IsDir:   fileInfo.IsDir(),
+                       Ino:     stat.Ino,
+               },
+       }
+       logger.Print("responded valid FileInfo. ", res.Result)
+       return res, nil
+}
+
+// TODO implement any locks here
+func (s *server) OpenDir(ctx context.Context, req *pb.OpenDirReq) 
(*pb.OpenDirRes, error) {
+       path := req.Name
+       rpcCtx := req.Context
+       logger.Print("received valid OpenDir request. ", path, rpcCtx)
+       res := &pb.OpenDirRes{
+               Result: &pb.OpenedDir{},
+       }
+       return res, nil
+}
+
+// TODO implement any locks here
+func (s *server) OpenFile(ctx context.Context, req *pb.OpenFileReq) 
(*pb.OpenFileRes, error) {
+       path := req.Name
+       rpcCtx := req.Context
+       logger.Print("received valid OpenFile request. ", path, rpcCtx)
+       res := &pb.OpenFileRes{
+               Result: &pb.OpenedFile{},
+       }
+       return res, nil
+}
+
+func (s *server) ReadDir(ctx context.Context, req *pb.ReadDirReq) 
(*pb.ReadDirRes, error) {
+       path := req.Name
+       rpcCtx := req.Context
+       logger.Print("received valid ReadDir request. ", path, rpcCtx)
+       entries, err := os.ReadDir(path)
+       if handleErr(err, "os.ReadDir failed") != nil {
+               return nil, err
+       }
+       resEntries := []*pb.DirEntry{}
+       for _, entry := range entries {
+               info, err := entry.Info()
+               if handleErr(err, "entry.Info() failed") != nil {
+                       return nil, err
+               }
+               obj := pb.DirEntry{
+                       Name:     entry.Name(),
+                       IsDir:    entry.IsDir(),
+                       FileMode: uint32(entry.Type()),
+                       Info: &pb.FileInfo{
+                               Name:    info.Name(),
+                               Size:    info.Size(),
+                               Mode:    uint32(info.Mode()),
+                               ModTime: timestamppb.New(info.ModTime()),
+                               IsDir:   info.IsDir(),
+                               Ino:     info.Sys().(*syscall.Stat_t).Ino,
+                       },
+               }
+               resEntries = append(resEntries, &obj)
+       }
+       res := &pb.ReadDirRes{
+               Result: resEntries,
+       }
+
+       return res, nil
+}
+
+func (s *server) ReadFile(ctx context.Context, req *pb.ReadFileReq) 
(*pb.ReadFileRes, error) {
+       path := req.Name
+       rpcCtx := req.Context
+       logger.Print("received valid ReadFile request. ", path, rpcCtx)
+       file, err := os.ReadFile(path)
+       if handleErr(err, "os.Stat failed") != nil {
+               return nil, err
+       }
+       // Only Dst is used
+       res := &pb.ReadFileRes{
+               Result: &pb.FileEntry{
+                       Dst: file,
+               },
+       }
+       return res, nil
+}
+
+func (s *server) WriteFile(ctx context.Context, req *pb.WriteFileReq) 
(*pb.WriteFileRes, error) {
+       path := req.Name
+       rpcCtx := req.Context
+       data := req.Data
+       offset := req.Offset
+       // TODO properly use offset
+       logger.Print("received valid WriteFile request. ", path, rpcCtx, offset)
+       err := os.WriteFile(path, data, 0666)
+       if handleErr(err, "os.WriteFile failed") != nil {
+               return nil, err
+       }
+       res := &pb.WriteFileRes{
+               Result: true,
+       }
+       return res, nil
+}
+
+func (s *server) SetInodeAtt(ctx context.Context, req *pb.SetInodeAttReq) 
(*pb.SetInodeAttRes, error) {
+       path := req.Name
+       rpcCtx := req.Context
+       // updated values
+       size := req.Size
+       mode := req.FileMode
+       atime := req.ATime
+       mtime := req.MTime
+       logger.Print("received valid SetInodeAtt request. ", path, rpcCtx, 
size, mode, atime, mtime)
+       if size != nil {
+               os.Truncate(path, int64(*size))
+       }
+       if mode != nil {
+               os.Chmod(path, os.FileMode(*mode))
+       }
+       if (atime != nil) && (mtime != nil) {
+               os.Chtimes(path, atime.AsTime(), mtime.AsTime())
+       }
+       // once updated, get and return latest values
+       fileInfo, err := os.Stat(path)
+       if handleErr(err, "os.Stat failed") != nil {
+               return nil, err
+       }
+       res := &pb.SetInodeAttRes{
+               Result: &pb.InodeAtt{
+                       Size:     uint64(fileInfo.Size()),
+                       FileMode: uint32(fileInfo.Mode()),
+                       Mtime:    timestamppb.New(fileInfo.ModTime()),
+                       Atime:    timestamppb.New(fileInfo.ModTime()),
+               },
+       }
+       return res, nil
+}
+
+func main() {
+
+       listener, err := net.Listen("tcp", "127.0.0.1:50000")
+       if handleErr(err, "Could not start GRPC server") != nil {
+               os.Exit(1)
+       }
+
+       s := grpc.NewServer()
+       pb.RegisterFuseServiceServer(s, &server{})
+
+       go s.Serve(listener)
+       logState("running until interrupt")
+
+       sigCh := make(chan os.Signal, 1)
+       signal.Notify(sigCh, os.Interrupt)
+       <-sigCh
+       logState("interrupt received, terminating.")
+}
diff --git a/modules/agent-framework/airavata-fuse/src/proto/grpcfs.proto 
b/modules/agent-framework/airavata-fuse/src/proto/grpcfs.proto
new file mode 100644
index 0000000000..31fd15999f
--- /dev/null
+++ b/modules/agent-framework/airavata-fuse/src/proto/grpcfs.proto
@@ -0,0 +1,120 @@
+syntax = "proto3";
+
+package pb;
+
+import "google/protobuf/timestamp.proto";
+
+option go_package="grpcfs/pb";
+
+// RPC Helper Context - Define as needed
+message RPCContext {
+       string GatewayId = 1;
+       string AccessToken = 2;
+       string AgentId = 3;
+}
+
+// Primitive
+message OpContext { uint64 FuseId = 1; uint64 Pid = 2; uint64 Uid = 3; }
+
+// Toplevel
+message StatFs {
+       uint32 BlockSize = 1;
+       uint64 Blocks = 2;
+    uint64 BlocksFree = 3;
+    uint64 BlocksAvailable = 4;
+       uint32 IoSize = 5;
+       uint64 Inodes = 6;
+       uint64 InodesFree = 7;
+}
+
+message FileInfo {
+       string Name = 1;
+       int64 Size = 2;
+       uint32 Mode = 3;
+       google.protobuf.Timestamp ModTime = 4;
+       bool IsDir = 5;
+       uint64 Ino = 6;
+}
+
+message OpenedDir {
+       uint64 Inode = 1;
+       uint64 Handle = 2;
+       OpContext OpContext = 3;
+       bool CacheDir = 4;
+       bool KeepCache = 5;
+}
+
+message OpenedFile {
+       uint64 Inode = 1;
+       uint64 Handle = 2;
+       bool KeepPageCache = 3;
+       bool UseDirectIO = 4;
+       uint32 OpenFlags = 5;
+       OpContext OpContext = 6;
+}
+
+message DirEntry {
+       string Name = 1;
+       bool IsDir = 2;
+       uint32 FileMode = 3;
+       FileInfo Info = 4;
+}
+
+message FileEntry {
+       uint64 Inode = 1;
+       uint64 Handle = 2;
+       int64 Offset = 3;
+       int64 Size = 4;
+       bytes Dst = 5;
+       repeated bytes Data = 6;
+       int32 BytesRead = 7;
+       OpContext OpContext = 8;
+}
+
+message InodeAtt {
+       uint64 Size = 1;
+       uint32 Nlink = 2;
+       uint32 FileMode = 3;
+       google.protobuf.Timestamp Atime = 5;
+       google.protobuf.Timestamp Mtime = 6;
+       google.protobuf.Timestamp Ctime = 7;
+}
+
+// Request Bodies
+message StatFsReq { string Name = 1; RPCContext Context = 2; }
+message FileInfoReq { string Name = 1; RPCContext Context = 2; }
+message OpenDirReq { string Name = 1; RPCContext Context = 2; }
+message OpenFileReq { string Name = 1; RPCContext Context = 2; }
+message ReadDirReq { string Name = 1; RPCContext Context = 2; }
+message ReadFileReq { string Name = 1; RPCContext Context = 2; }
+message WriteFileReq { string Name = 1; RPCContext Context = 2; bytes Data = 
3; int64 Offset = 4; }
+message SetInodeAttReq {
+       string Name = 1;
+       RPCContext Context = 2;
+       optional uint64 Size = 3;
+       optional uint32 FileMode = 4;
+       optional google.protobuf.Timestamp ATime = 5;
+       optional google.protobuf.Timestamp MTime = 6;
+}
+
+// Response Bodies
+message StatFsRes { StatFs Result = 1; }
+message FileInfoRes { FileInfo Result = 1; }
+message OpenDirRes { OpenedDir Result = 1; }
+message OpenFileRes { OpenedFile Result = 1; }
+message ReadDirRes { repeated DirEntry Result = 1; }
+message ReadFileRes { FileEntry Result = 1; }
+message WriteFileRes { bool Result = 1; }
+message SetInodeAttRes {InodeAtt Result = 1;}
+
+// Service Definition
+service FuseService {
+       rpc StatFs(StatFsReq) returns (StatFsRes) {}
+       rpc FileInfo(FileInfoReq) returns (FileInfoRes) {}
+       rpc OpenDir(OpenDirReq) returns (OpenDirRes) {}
+       rpc OpenFile(OpenFileReq) returns (OpenFileRes) {}
+       rpc ReadDir(ReadDirReq) returns (ReadDirRes) {}
+       rpc ReadFile(ReadFileReq) returns (ReadFileRes) {}
+       rpc WriteFile(WriteFileReq) returns (WriteFileRes) {}
+       rpc SetInodeAtt(SetInodeAttReq) returns (SetInodeAttRes) {}
+}

Reply via email to