forked from crc-org/crc
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Client code will run in the guest, but only need to get a vsock/tcp file descriptor, and pass this to the mount command. still todo: - sync the split of StartShares/StartVsockShares with podman - probably need to be able to pass or return an errCh to the 9p code for better error reporting - shares must be started/stopped at the same time as the VM, but must live in the daemon - new daemon entrypoint? could be the client code in the daemon which makes a request to the guest daemon endpoint to start sharing?
- Loading branch information
Showing
59 changed files
with
10,021 additions
and
119 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package plan9 | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
|
||
"github.com/sirupsen/logrus" | ||
) | ||
|
||
// from /etc/services: | ||
// 9pfs 564/tcp # plan 9 file service | ||
const Port = 564 | ||
const PortStr = "564" | ||
|
||
type Mount struct { | ||
Listener net.Listener | ||
Path string | ||
} | ||
|
||
func StartShares(plan9Mounts []Mount) (defErr error) { | ||
for _, m := range plan9Mounts { | ||
server, err := New9pServer(m.Listener, m.Path) | ||
if err != nil { | ||
return fmt.Errorf("serving directory %s on vsock %s: %w", m.Path, m.Listener.Addr().String(), err) | ||
} | ||
defer func() { | ||
if defErr != nil { | ||
if err := server.Stop(); err != nil { | ||
logrus.Errorf("Error stopping 9p server: %v", err) | ||
} | ||
} | ||
}() | ||
|
||
serverDir := m.Path | ||
|
||
go func() { | ||
if err := server.WaitForError(); err != nil { | ||
logrus.Errorf("Error from 9p server for %s: %v", serverDir, err) | ||
} else { | ||
// We do not expect server exits - this should | ||
// run until the program exits. | ||
logrus.Warnf("9p server for %s exited without error", serverDir) | ||
} | ||
}() | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package plan9 | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/linuxkit/virtsock/pkg/hvsock" | ||
"github.com/sirupsen/logrus" | ||
) | ||
|
||
// StartVsockShares serving the given shares on Windows HVSocks for use by a Hyper-V VM. | ||
// Mounts is formatted as a map of directory to be shared to vsock GUID. | ||
// The vsocks used must already be defined before StartVsockShares is called; it's | ||
// expected that the vsocks will be created and torn down by the program calling | ||
// gvproxy. | ||
func StartVsockShares(mounts map[string]string) (defErr error) { | ||
plan9Mounts := []Mount{} | ||
for path, guid := range mounts { | ||
service, err := hvsock.GUIDFromString(guid) | ||
if err != nil { | ||
return fmt.Errorf("parsing vsock guid %s: %w", guid, err) | ||
} | ||
|
||
listener, err := hvsock.Listen(hvsock.Addr{ | ||
VMID: hvsock.GUIDWildcard, | ||
ServiceID: service, | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("retrieving listener for vsock %s: %w", guid, err) | ||
} | ||
|
||
logrus.Debugf("Going to serve directory %s on vsock %s", path, guid) | ||
plan9Mounts = append(plan9Mounts, Mount{Listener: listener, Path: path}) | ||
} | ||
return StartShares(plan9Mounts) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package plan9 | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/hugelgupf/p9/fsimpl/localfs" | ||
"github.com/hugelgupf/p9/p9" | ||
"github.com/sirupsen/logrus" | ||
) | ||
|
||
type Server struct { | ||
server *p9.Server | ||
// TODO: Once server has a proper Close() we don't need this. | ||
// This is basically just a short-circuit to actually close the server | ||
// without that ability. | ||
listener net.Listener | ||
// Errors from the server being started will come out here. | ||
errChan chan error | ||
} | ||
|
||
// Expose a single directory (and all children) via the given net.Listener. | ||
// Directory given must be an absolute path and must exist. | ||
func New9pServer(listener net.Listener, exposeDir string) (*Server, error) { | ||
// Verify that exposeDir makes sense. | ||
if !filepath.IsAbs(exposeDir) { | ||
return nil, fmt.Errorf("path to expose to machine must be absolute: %s", exposeDir) | ||
} | ||
stat, err := os.Stat(exposeDir) | ||
if err != nil { | ||
return nil, fmt.Errorf("cannot stat path to expose to machine: %w", err) | ||
} | ||
if !stat.IsDir() { | ||
return nil, fmt.Errorf("path to expose to machine must be a directory: %s", exposeDir) | ||
} | ||
|
||
server := p9.NewServer(localfs.Attacher(exposeDir), []p9.ServerOpt{}...) | ||
if server == nil { | ||
return nil, fmt.Errorf("p9.NewServer returned nil") | ||
} | ||
|
||
errChan := make(chan error) | ||
|
||
// TODO: Use a channel to pass back this if it occurs within a | ||
// reasonable timeframe. | ||
go func() { | ||
errChan <- server.Serve(listener) | ||
close(errChan) | ||
}() | ||
|
||
toReturn := new(Server) | ||
toReturn.listener = listener | ||
toReturn.server = server | ||
toReturn.errChan = errChan | ||
|
||
// Just before returning, check to see if we got an error off server | ||
// startup. | ||
select { | ||
case err := <-errChan: | ||
return nil, fmt.Errorf("starting 9p server: %w", err) | ||
default: | ||
logrus.Infof("Successfully started 9p server for directory %s", exposeDir) | ||
} | ||
|
||
return toReturn, nil | ||
} | ||
|
||
// Stop a running server. | ||
// Please note that this does *BAD THINGS* to clients if they are still running | ||
// when the server stops. Processes get stuck in I/O deep sleep and zombify, and | ||
// nothing I do save restarting the VM can remove the zombies. | ||
func (s *Server) Stop() error { | ||
if s.server != nil { | ||
if err := s.listener.Close(); err != nil { | ||
return err | ||
} | ||
s.server = nil | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Wait for an error from a running server. | ||
func (s *Server) WaitForError() error { | ||
if s.server != nil { | ||
err := <-s.errChan | ||
return err | ||
} | ||
|
||
// Server already down, return nil | ||
return nil | ||
} |
Oops, something went wrong.