-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
service daemon #9
Conversation
Status update: I'll try to detail the changes better later but some things are:
|
I'm glad you got back to working on this 9p stuff. How can I help? Are you going to have a demo ready for IPFS Camp? ;-) One thing I'm tempted to do is try to build a 9p VFS for Qt, in the hope that this will actually get integrated. (So you could perhaps browse and load files from it via an ordinary file dialog, without necessarily needing to mount it first.) I could do that with the http client interface, but 9p is going to end up better and faster, right? Is it realistic that we can have the 9p file server as a feature in kubo? I see that the fuse mounts are still missing so many features. (listing pins, listing or catting CIDs, writing anything... and if ipns is mounted, then |
:^]
Good question.
No demos planned, but I might make a screencast that shows off how this 9P API server works in its current state.
That sounds great. I've had this on my mind recently as well. Exposing 9P2000.L through QT would be cool. Something I'm going to need to implement later is a Windows shell extension of the context-menu, which compares the path it receives, from (virtual) mountpoint files hosted on the 9P server.
Most likely not. The lack of development on their FUSE implementation, and relevant technologies like UFS2 (and even 1.5), imo - add to this sentiment of disinterest. If you want those bridges, you have to build them yourself, separate from an IPFS implementation. I think the prototypes that have been published already, show that it's possible for us to get there. |
We should chat on IRC or Telegram or whatever you use. I've always been a bit frustrated with what's missing in IPFS, sounds like you are too. Maybe forking and overtaking them is the answer? I just can't understand PL's approach: every application is to be a one-off that has its own daemon linked in? Or they really only care about how the web will use it, not so much about desktop operating systems? The way I see it, ipfs should be a system daemon, like sshd, so its client interface needs to satisfy all the use cases. It has to manage storage, it does a lot of communication, and so there's no justification to run more than one instance on your system. I was at IPFS Camp last time and never really got a straight answer about that. We discussed nitty-gritty details about future UnixFS implementation (for example) rather than the part about how to fulfill the interface requirement that is implied by the "FS" in the name. And AFAIK not much got done since then. I don't know if I go again, whether to expect finally some sort of enlightenment, or I'm just beating a dead horse. I'm not sure whether I can really get support for other URL schemes into a file dialog; there is this warning "Non-native QFileDialog supports only local files". But we at Qt (and David Faure from KDE) have done some work to use QUrl everywhere that a path was used before, and we have QFileDialog::setSupportedSchemes() for some reason. As if we were going to support non-file URLs. Of course I can implement a new dialog, maybe have to do that for now. At least stuff like QDir and QFileInfo and QIODevice work with non-filesystem data sources. To make a new virtual filesystem, you have a choice: implement a KIO slave (I did that already in 2019, using the IPFS HTTP API), but that won't work with Qt 6 yet: KDE has been too slow getting their stuff ported. And KIO's approach to asynchronous API is unconventional: separate processes are started. (Which I was thinking the other day is actually quite conventional on Plan 9, but my instinct is to think it's gross on Linux. Maybe I'm wrong, should just get used to it.) Or, implement a QAbstractFileEngine subclass. That's private API, but it didn't change for a long time either; so I guess I'll try that. But we know we need to replace it eventually. See also https://bugreports.qt.io/browse/QTBUG-103246 : interesting discussion there. Or, maybe implementing a GVfs is an alternative... just a very unfamiliar one for me. At least Qt can use the GTK file dialog, optionally. I agree that conceptually it's best to mount the FS somehow. That's what I want. But there are many issues:
I don't know if you care about Plan 9 or not. Anyway 9p could be a good way to mount filesystems across OSes. I believe it must work well, but in practice I've been messing around and haven't gotten a really smooth experience with it yet. (One experiment is with http://wiki.call-cc.org/eggref/4/9p which implements only core 9p, not the Linux extensions. So I have to use 9pfs, not the kernel client.) Will keep trying. But on the other hand: it so happens that Go runs on Plan 9 (as long as you aren't running a 64-bit ARM, anyway). So in theory, we should be able to get a mountable IPFS working there. Wouldn't that be sweet? |
@ec1oud
For sure :^)
Yeah, I only downloaded it in the first place because it claimed to have Windows and mount support.
Hard to say. I'd rather collaborate than compete.
From what I gather, it seems like they want this too. And that's how we use it here.
UFS 1.5 would be nice to have for timestamps when I re-write the interface between MFS <-> golang's
Interesting stuff. I'm glad to hear about the path abstractions, and the IPFS client VFS.
I think it depends on the implementation. I think this 9P daemon would be well suited as a guest process (e.g. within a Qt host). Once I finish my current refactor, I'll make that screencast talking about it. Banging my head against something first.
So the MFS and write portions of the IPNS implementations I had, worked this way already. That implementation worked generally with UnixFS CIDs. I don't know what the latest version is of it, but here's an ancient reference {/mfs, /ufs} but isn't worth reading since it's going to change.)
Ugh. This is one I'll have to read into more and see if we can focus on it during development. My presumption though is that all we can do is make tolerances configurable. Maybe some gross AIO wrappers around remote IO interface in a funny way.
I can't say I've had any issues that weren't my own fault, but I'm also not doing anything terrible complex yet. And I know there have been bugs in the kernel for 9P before.
Yeah, unfortunately I'm likely going to have to do this on Windows as well. NT has a native 9P2000.L client and server implementation (for their WSL tech), but it's API is not public. So despite this, we can only mount remote 9P servers via WinFSP, not natively.
I know what you mean. This came up when we were prototyping and it was interesting to consider, but we didn't go far with it. Because while it works natively, we knew the feature set would have to accommodate a variety of restrictions across operating systems, at least right now. But it's something of interest to me too.
Yeah it's an interesting thing and I go back and forth on it; but generally I like the idea of these ad-hoc conventions. I was thinking recently if it would be a good idea to start include text data as a special path/hidden-file in my own 9P file systems. Then, if you have to do out of band stuff or other coordination, etc. it's at least bundled with the API directory you're actively manipulating.
The more I learn about it, the more I like it. The only things I don't like about it are that it's concepts and technologies aren't more widely used. ;^) Nice. Lisps and Lua come up regularly when me and my associate talk about this stuff.
It's by no accident that all these components were chosen together. Portability is paramount to me personally, and after evaluating the whole gambit, these provided the best balance I could find (at least for me). The old |
Small status update here. Long version: This server implements our own API and exposes it via a 9P file system (in-proc interface + optionally exposed as a server), and one of our file system hosting options is also a 9P file system (e.g. IPFS -> 9P or any Go So it makes sense to share code and data structures between these and other components later that will integrate with this utility. Logically, the solutions to the problems I'm facing are simple and straight forward, however I'm getting caught up fighting with the compiler. Falling back to the older Go spec, I'm having to lean slightly on dynamic things like runtime/reflection magic; which isn't ideal, but its use is minimal. Ideally this would be removed later as Go's spec changes, so that more things are checked at compile time. All that said, I admittedly have not been able to spend as much time focusing on this recently as I would have liked. Mainly due to personal problems of my own doing, but I expect those problems to not affect me anymore. And I expect to be able to give this proper attention again, instead of looking at it and going "wow this is hard, I'm giving up immediately / will do it tomorrow". |
This feature was reworked heavily, and while still not "complete", we'll be moving away from trying to push things into master when finished and instead will just adopt the more modern practice of putting things into master and incrementally improving them over time instead. |
Follow up to #3
We're implementing things via a "client and server" model, but it's actually more just like "remote and persist".
Between calls to things like
fs mount
,fs list
, etc. we need somewhere to store and share persistent/session data, and this seems like a sensible and portable way to handle it compared to other strategies like shared memory, or whatever else.It also easily allows us to do privilege separation.
The daemon can run in the background with higher privileges, while less authoritative clients can just make requests to it.
There's potential to do other fancy remote things with this since we expect to communicate over local sockets, but that's not really the focus for now.
Implementation:
We're ditching the previous HTTP RPC library that was inherited from the old repo and starting fresh with a 9P based server that is arguably simpler to use and reason about.
Abstractions are intended to be file systems, with basic I/O operations not too dissimilar to how people use REST.
Listening sockets are files in a directory, the mount table should be some similar abstraction, etc.
We basically just need some abstract tree where we can hold data across calls, and access/manipulate it via some remote client.
Ideally, the abstractions for these should be layered well.
With file abstractions being implemented independently. ("socket files are socket files")
Construction being done via composition. ("the server makes a bunch of socket files on startup and stores them in some directory")
APIs having default expectations, but not lacking in configuration. ("
clientApi.Shutdown(sockName, opts...)
will walk to the socket file, and do the closer dance with it")With higher APIs just gluing it together ("from the CLI it's
fs.exe shutdown sockName
")Something like that.
Status:
The concept seems to be viable enough to publish this draft, but the implementations still need to be completed.
As-is we can listen on a socket, mount the server's root on Linux via
mount -t 9p 192.168.1.40 /mnt/9 -o "trans=tcp,port=564"
and close those listeners via standard file system writesprintf desino>/mnt/9/listeners/192.168.1.40\:564; umount /mnt/9
Doing this from a cli program is basically the same procedure, abstracted in Go.
client := connect(...); open("the file"); write("shutdown key"); close("the file"); client.Close
This pattern should follow for all of our commands server and client side.
The prototype we developed (*not useful, correct, or pretty) exists here: https://github.com/djdv/go-filesystem-utils/tree/j/D9
which shows a simple "MOTD" server.
It can act as another example of how we'll likely implement
mount
,unmount
, andlist
. (Except less crude, and more spec correct)TODO:
Lots.
The commits need to be split up logically, some things need to be backported to the commands branch.
Tests / spec correctness is important.
This message needs to be more coherent.