Skip to content

Commit

Permalink
Merge pull request #1108 from jcrussell/issue-1107
Browse files Browse the repository at this point in the history
minimega/ron/miniccc: add ufs to miniccc
  • Loading branch information
djfritz committed Jun 21, 2018
2 parents 79b1ef5 + 14fb518 commit 85cf7f7
Show file tree
Hide file tree
Showing 39 changed files with 5,926 additions and 80 deletions.
1 change: 1 addition & 0 deletions LICENSES/LICENSE.ninep
23 changes: 23 additions & 0 deletions doc/content/articles/tutorials/cc.article
Expand Up @@ -228,6 +228,29 @@ the receive command.

.mega cc/recv2.mm

** Full filesystem access

The `cc`mount` can be used to mount the guest filesystem on the host. This is
accomplished by a 9p server integrated into miniccc that serves the guest's
filesystem over the existing connection to the command and control server.
`cc`mount` is fully integrated with namespaces -- you may mount a VM's
filesystem to the head node, regardless of which host is actually running the
VM. In order to mount the filesystem, you'll need to use either the name or
UUID of the VM:

cc mount vm-0 /mnt

To list existing mounts, run it with no arguments:

cc mount

You can unmount a specific VM or mount by path using:

clear cc mount [uuid or name or path].

Without an argument, `clear`cc`mount` clears all mounts. This also occurs when
you call `clear`cc`.

* Examining Responses

We've seen the use of `cc`responses` several times so far. The `responses`
Expand Down
2 changes: 2 additions & 0 deletions src/miniccc/mux.go
Expand Up @@ -60,6 +60,8 @@ func mux() {
_, err = remote.Write(m.Tunnel)
case ron.MESSAGE_PIPE:
pipeMessage(&m)
case ron.MESSAGE_UFS:
ufsMessage(&m)
default:
err = fmt.Errorf("unknown message type: %v", m.Type)
}
Expand Down
100 changes: 100 additions & 0 deletions src/miniccc/ufs.go
@@ -0,0 +1,100 @@
// Copyright (2014) Sandia Corporation.
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.

package main

import (
log "minilog"
"net"
"os"
"path/filepath"
"ron"
"runtime"

"github.com/Harvey-OS/ninep/filesystem"
"github.com/Harvey-OS/ninep/protocol"
)

var rootFS struct {
// embed
*protocol.Server

running bool

// active connection, set when running
remote, local net.Conn
}

// ufsMessage handles a message from the server and relays it to UFS
func ufsMessage(m *ron.Message) {
switch m.UfsMode {
case ron.UFS_OPEN:
if rootFS.running {
log.Error("ufs is already running")
return
}

if rootFS.Server == nil {
log.Info("init rootFS")
root := "/"
if runtime.GOOS == "windows" {
// TODO: what if there is more that one volume?
root = filepath.VolumeName(os.Getenv("SYSTEMROOT")) + "\\"
}

fs, err := ufs.NewServer(ufs.Root(root), ufs.Trace(log.Debug))
if err != nil {
log.Error("unable to create file server: %v", err)
return
}

ps, err := protocol.NewServer(fs, protocol.Trace(log.Debug))
if err != nil {
log.Error("unable to create ninep server: %v", err)
return
}
rootFS.Server = ps

log.Info("init'd rootFS")
}

rootFS.running = true

rootFS.remote, rootFS.local = net.Pipe()

go ron.Trunk(rootFS.remote, client.UUID, ufsSendMessage)

log.Info("accepting tunneled connection")

if err := rootFS.Accept(rootFS.local); err != nil {
log.Error("ufs error: %v", err)
rootFS.running = false
}
case ron.UFS_CLOSE:
if !rootFS.running {
log.Error("ufs not running")
return
}

rootFS.running = false
rootFS.remote.Close()
case ron.UFS_DATA:
if !rootFS.running {
log.Error("ufs not running")
return
}

// relay the Tunnel data from ron
rootFS.remote.Write(m.Tunnel)
}
}

// ufsSendMessage tweaks the message generated by ron.Trunk before calling
// sendMessage.
func ufsSendMessage(m *ron.Message) error {
m.Type = ron.MESSAGE_UFS
m.UfsMode = ron.UFS_DATA

return sendMessage(m)
}

0 comments on commit 85cf7f7

Please sign in to comment.