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
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lg := slog.With("backend", shareBackendFlag)
|
||||||
|
|
||||||
shareURI, err := backend.Apply(ctx, sharePWD, &share.VMShareContext{
|
shareURI, err := backend.Apply(ctx, sharePWD, &share.VMShareContext{
|
||||||
Instance: i,
|
Instance: i,
|
||||||
FileManager: fm,
|
FileManager: fm,
|
||||||
NetTapCtx: tapCtx,
|
NetTapCtx: tapCtx,
|
||||||
})
|
})
|
||||||
if err != nil {
|
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
|
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)
|
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")
|
bc.logger.Info("VM OS installation in progress")
|
||||||
|
|
||||||
// TODO: Compile select features only.
|
err = runAlpineSetupCmd(sc, []string{"openssh", "lvm2", "util-linux", "cryptsetup", "vsftpd", "samba", "netatalk"})
|
||||||
err = runAlpineSetupCmd(sc, []string{"openssh", "lvm2", "util-linux", "cryptsetup", "vsftpd", "samba"})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "run alpine setup cmd")
|
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{
|
var backends = map[string]NewBackendFunc{
|
||||||
"ftp": NewFTPBackend,
|
"ftp": NewFTPBackend,
|
||||||
"smb": NewSMBBackend,
|
"smb": NewSMBBackend,
|
||||||
|
"afp": NewAFPBackend,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Will return nil if no backend is found.
|
// Will return nil if no backend is found.
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/AlexSSD7/linsk/vm"
|
"github.com/AlexSSD7/linsk/vm"
|
||||||
"github.com/pkg/errors"
|
"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")
|
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
|
return "ftp://" + b.extIP.String() + ":" + fmt.Sprint(b.sharePort), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,16 +7,12 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/AlexSSD7/linsk/vm"
|
"github.com/AlexSSD7/linsk/vm"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const smbPort = 445
|
const smbPort = 445
|
||||||
|
|
||||||
// TODO: Test SMB backend on macOS.
|
|
||||||
|
|
||||||
type SMBBackend struct {
|
type SMBBackend struct {
|
||||||
listenIP net.IP
|
listenIP net.IP
|
||||||
sharePort *uint16
|
sharePort *uint16
|
||||||
|
|
@ -63,8 +59,6 @@ func (b *SMBBackend) Apply(ctx context.Context, sharePWD string, vc *VMShareCont
|
||||||
return "", errors.Wrap(err, "start smb server")
|
return "", errors.Wrap(err, "start smb server")
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Info("Started the network share successfully", "type", "smb", "ext", vc.NetTapCtx != nil)
|
|
||||||
|
|
||||||
var shareURL string
|
var shareURL string
|
||||||
if b.sharePort != nil {
|
if b.sharePort != nil {
|
||||||
shareURL = "smb://" + net.JoinHostPort(b.listenIP.String(), fmt.Sprint(*b.sharePort)) + "/linsk"
|
shareURL = "smb://" + net.JoinHostPort(b.listenIP.String(), fmt.Sprint(*b.sharePort)) + "/linsk"
|
||||||
|
|
|
||||||
|
|
@ -284,7 +284,8 @@ writeable = yes
|
||||||
path = /mnt
|
path = /mnt
|
||||||
force user = linsk
|
force user = linsk
|
||||||
force group = linsk
|
force group = linsk
|
||||||
create mask = 0664`
|
create mask = 0664
|
||||||
|
`
|
||||||
|
|
||||||
err = scpClient.CopyFile(scpCtx, strings.NewReader(sambaCfg), "/etc/samba/smb.conf", "0400")
|
err = scpClient.CopyFile(scpCtx, strings.NewReader(sambaCfg), "/etc/samba/smb.conf", "0400")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -312,3 +313,53 @@ create mask = 0664`
|
||||||
|
|
||||||
return nil
|
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