Initial AFP support implementation
This commit is contained in:
parent
73a7d2cd18
commit
7ba79ff803
7 changed files with 100 additions and 15 deletions
|
|
@ -72,17 +72,19 @@ var runCmd = &cobra.Command{
|
|||
return 1
|
||||
}
|
||||
|
||||
lg := slog.With("backend", shareBackendFlag)
|
||||
|
||||
shareURI, err := backend.Apply(ctx, sharePWD, &share.VMShareContext{
|
||||
Instance: i,
|
||||
FileManager: fm,
|
||||
NetTapCtx: tapCtx,
|
||||
})
|
||||
if err != nil {
|
||||
slog.Error("Failed to apply (start) file share backend", "backend", shareBackendFlag, "error", err.Error())
|
||||
lg.Error("Failed to apply (start) file share backend", "error", err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
slog.Info("Started the network share successfully", "type", "ftp")
|
||||
lg.Info("Started the network share successfully")
|
||||
|
||||
fmt.Fprintf(os.Stderr, "===========================\n[Network File Share Config]\nThe network file share was started. Please use the credentials below to connect to the file server.\n\nType: "+strings.ToUpper(shareBackendFlag)+"\nURL: %v\nUsername: linsk\nPassword: %v\n===========================\n", shareURI, sharePWD)
|
||||
|
||||
|
|
|
|||
|
|
@ -157,8 +157,7 @@ func (bc *BuildContext) BuildWithInterruptHandler() error {
|
|||
|
||||
bc.logger.Info("VM OS installation in progress")
|
||||
|
||||
// TODO: Compile select features only.
|
||||
err = runAlpineSetupCmd(sc, []string{"openssh", "lvm2", "util-linux", "cryptsetup", "vsftpd", "samba"})
|
||||
err = runAlpineSetupCmd(sc, []string{"openssh", "lvm2", "util-linux", "cryptsetup", "vsftpd", "samba", "netatalk"})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "run alpine setup cmd")
|
||||
}
|
||||
|
|
|
|||
42
share/afp.go
Normal file
42
share/afp.go
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/AlexSSD7/linsk/vm"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type AFPBackend struct {
|
||||
listenIP net.IP
|
||||
sharePort uint16
|
||||
}
|
||||
|
||||
func NewAFPBackend(uc *UserConfiguration) (Backend, *VMShareOptions, error) {
|
||||
sharePort, err := getNetworkSharePort(0)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "get network share port")
|
||||
}
|
||||
|
||||
return &AFPBackend{
|
||||
listenIP: uc.listenIP,
|
||||
sharePort: sharePort,
|
||||
}, &VMShareOptions{
|
||||
Ports: []vm.PortForwardingRule{{
|
||||
HostIP: uc.listenIP,
|
||||
HostPort: sharePort,
|
||||
VMPort: 548,
|
||||
}},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *AFPBackend) Apply(ctx context.Context, sharePWD string, vc *VMShareContext) (string, error) {
|
||||
err := vc.FileManager.StartAFP(sharePWD)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "start afp server")
|
||||
}
|
||||
|
||||
return "afp://" + net.JoinHostPort(b.listenIP.String(), fmt.Sprint(b.sharePort)) + "/linsk", nil
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ type Backend interface {
|
|||
var backends = map[string]NewBackendFunc{
|
||||
"ftp": NewFTPBackend,
|
||||
"smb": NewSMBBackend,
|
||||
"afp": NewAFPBackend,
|
||||
}
|
||||
|
||||
// Will return nil if no backend is found.
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
|
||||
"log/slog"
|
||||
|
||||
"github.com/AlexSSD7/linsk/vm"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
|
@ -61,7 +59,5 @@ func (b *FTPBackend) Apply(ctx context.Context, sharePWD string, vc *VMShareCont
|
|||
return "", errors.Wrap(err, "start ftp server")
|
||||
}
|
||||
|
||||
slog.Info("Started the network share successfully", "type", "ftp")
|
||||
|
||||
return "ftp://" + b.extIP.String() + ":" + fmt.Sprint(b.sharePort), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,16 +7,12 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
|
||||
"log/slog"
|
||||
|
||||
"github.com/AlexSSD7/linsk/vm"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const smbPort = 445
|
||||
|
||||
// TODO: Test SMB backend on macOS.
|
||||
|
||||
type SMBBackend struct {
|
||||
listenIP net.IP
|
||||
sharePort *uint16
|
||||
|
|
@ -63,8 +59,6 @@ func (b *SMBBackend) Apply(ctx context.Context, sharePWD string, vc *VMShareCont
|
|||
return "", errors.Wrap(err, "start smb server")
|
||||
}
|
||||
|
||||
slog.Info("Started the network share successfully", "type", "smb", "ext", vc.NetTapCtx != nil)
|
||||
|
||||
var shareURL string
|
||||
if b.sharePort != nil {
|
||||
shareURL = "smb://" + net.JoinHostPort(b.listenIP.String(), fmt.Sprint(*b.sharePort)) + "/linsk"
|
||||
|
|
|
|||
|
|
@ -284,7 +284,8 @@ writeable = yes
|
|||
path = /mnt
|
||||
force user = linsk
|
||||
force group = linsk
|
||||
create mask = 0664`
|
||||
create mask = 0664
|
||||
`
|
||||
|
||||
err = scpClient.CopyFile(scpCtx, strings.NewReader(sambaCfg), "/etc/samba/smb.conf", "0400")
|
||||
if err != nil {
|
||||
|
|
@ -312,3 +313,53 @@ create mask = 0664`
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fm *FileManager) StartAFP(pwd string) error {
|
||||
// This timeout is for the SCP client exclusively.
|
||||
scpCtx, scpCtxCancel := context.WithTimeout(fm.vm.ctx, time.Second*5)
|
||||
defer scpCtxCancel()
|
||||
|
||||
scpClient, err := fm.vm.DialSCP()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "dial scp")
|
||||
}
|
||||
|
||||
defer scpClient.Close()
|
||||
|
||||
afpCfg := `[Global]
|
||||
|
||||
[linsk]
|
||||
path = /mnt
|
||||
file perm = 0664
|
||||
directory perm = 0775
|
||||
valid users = linsk
|
||||
force user = linsk
|
||||
force group = linsk
|
||||
`
|
||||
|
||||
err = scpClient.CopyFile(scpCtx, strings.NewReader(afpCfg), "/etc/afp.conf", "0400")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "copy netatalk config file")
|
||||
}
|
||||
|
||||
scpClient.Close()
|
||||
|
||||
sc, err := fm.vm.DialSSH()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "dial ssh")
|
||||
}
|
||||
|
||||
defer func() { _ = sc.Close() }()
|
||||
|
||||
_, err = sshutil.RunSSHCmd(fm.vm.ctx, sc, "rc-update add netatalk && rc-service netatalk start")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "add and start netatalk service")
|
||||
}
|
||||
|
||||
err = sshutil.ChangeUnixPass(fm.vm.ctx, sc, "linsk", pwd)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "change unix pass")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue