Skip to content
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

Supervisor standalone win #2381

Merged
merged 3 commits into from Jun 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 9 additions & 17 deletions cmd/supervisor/supervisor.go
Expand Up @@ -18,46 +18,38 @@
package main

import (
"flag"
"fmt"
"os"
"path/filepath"

"github.com/mysteriumnetwork/node/metadata"
"github.com/mysteriumnetwork/node/supervisor/daemon/transport"
"github.com/mysteriumnetwork/node/supervisor/logconfig"
"github.com/rs/zerolog"
"github.com/mysteriumnetwork/node/supervisor/svflags"
"github.com/rs/zerolog/log"

"github.com/mysteriumnetwork/node/supervisor/config"
"github.com/mysteriumnetwork/node/supervisor/daemon"
"github.com/mysteriumnetwork/node/supervisor/install"
)

var (
flagVersion = flag.Bool("version", false, "Print version")
flagInstall = flag.Bool("install", false, "Install or repair myst supervisor")
flagUninstall = flag.Bool("uninstall", false, "Uninstall myst supervisor")
logFilePath = flag.String("log-path", "", "Supervisor log file path")
logLevel = flag.String("log-level", zerolog.InfoLevel.String(), "Logging level")
)

func main() {
flag.Parse()
svflags.Parse()

if *flagVersion {
if *svflags.FlagVersion {
fmt.Println(metadata.VersionAsString())
os.Exit(0)
}

logOpts := logconfig.LogOptions{
LogLevel: *logLevel,
Filepath: *logFilePath,
LogLevel: *svflags.FlagLogLevel,
Filepath: *svflags.FlagLogFilePath,
}
if err := logconfig.Configure(logOpts); err != nil {
log.Fatal().Err(err).Msg("Failed to configure logging")
}

if *flagInstall {
if *svflags.FlagInstall {
path, err := thisPath()
if err != nil {
log.Fatal().Err(err).Msg("Failed to determine supervisor's path")
Expand All @@ -71,7 +63,7 @@ func main() {
log.Fatal().Err(err).Msg("Failed to install supervisor")
}
log.Info().Msg("Supervisor installed")
} else if *flagUninstall {
} else if *svflags.FlagUninstall {
log.Info().Msg("Uninstalling supervisor")
if err := install.Uninstall(); err != nil {
log.Fatal().Err(err).Msg("Failed to uninstall supervisor")
Expand All @@ -80,7 +72,7 @@ func main() {
} else {
log.Info().Msg("Running myst supervisor daemon")
supervisor := daemon.New(&config.Config{})
if err := supervisor.Start(); err != nil {
if err := supervisor.Start(transport.Options{WinService: *svflags.FlagWinService}); err != nil {
log.Fatal().Err(err).Msg("Error running supervisor")
}
}
Expand Down
4 changes: 2 additions & 2 deletions supervisor/daemon/daemon.go
Expand Up @@ -51,7 +51,7 @@ func New(cfg *config.Config) Daemon {
}

// Start supervisor daemon. Blocks.
func (d *Daemon) Start() error {
func (d *Daemon) Start(options transport.Options) error {
db, err := boltdb.NewStorage(os.TempDir())
if err != nil {
log.Err(err).Msg("Failed to init routes storage")
Expand All @@ -60,7 +60,7 @@ func (d *Daemon) Start() error {
netutil.ClearStaleRoutes()
}

return transport.Start(d.dialog)
return transport.Start(d.dialog, options)
}

// dialog talks to the client via established connection.
Expand Down
5 changes: 5 additions & 0 deletions supervisor/daemon/transport/transport.go
Expand Up @@ -21,3 +21,8 @@ import "io"

// handlerFunc talks to a connected client.
type handlerFunc func(conn io.ReadWriter)

// Options for transport.
type Options struct {
WinService bool
}
2 changes: 1 addition & 1 deletion supervisor/daemon/transport/transport_darwin.go
Expand Up @@ -29,7 +29,7 @@ const sock = "/var/run/myst.sock"

// Start starts a listener on a unix domain socket.
// Conversation is handled by the handlerFunc.
func Start(handle handlerFunc) error {
func Start(handle handlerFunc, _ Options) error {
if err := os.RemoveAll(sock); err != nil {
return fmt.Errorf("could not remove sock: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion supervisor/daemon/transport/transport_linux.go
Expand Up @@ -21,6 +21,6 @@ import "errors"

// Start starts a listener on a unix domain socket.
// Conversation is handled by the handlerFunc.
func Start(handle handlerFunc) error {
func Start(handle handlerFunc, _ Options) error {
return errors.New("not implemented")
}
15 changes: 10 additions & 5 deletions supervisor/daemon/transport/transport_windows.go
Expand Up @@ -31,20 +31,25 @@ const sock = `\\.\pipe\mystpipe`

// Start starts a listener on a unix domain socket.
// Conversation is handled by the handlerFunc.
func Start(handle handlerFunc) error {
return svc.Run("MysteriumVPNSupervisor", &managerService{handle: handle})
func Start(handle handlerFunc, options Options) error {
if options.WinService {
return svc.Run("MysteriumVPNSupervisor", &managerService{handle: handle})
} else {
return listenPipe(handle)
}
}

type managerService struct {
handle handlerFunc
}

// Execute is an entrypoint for a windows service.
func (m *managerService) Execute(args []string, r <-chan svc.ChangeRequest, s chan<- svc.Status) (svcSpecificEC bool, exitCode uint32) {
const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown | svc.AcceptPauseAndContinue

s <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
go func() {
if err := m.listenPipe(); err != nil {
if err := listenPipe(m.handle); err != nil {
log.Err(err).Msgf("Could not listen pipe on %s", sock)
}
}()
Expand All @@ -66,7 +71,7 @@ func (m *managerService) Execute(args []string, r <-chan svc.ChangeRequest, s ch
return
}

func (m *managerService) listenPipe() error {
func listenPipe(handle handlerFunc) error {
// TODO: Check these permissions, it would be much more secure to pass user id
// during supervisor installation as adding whole Users group is not secure.
socketGroup := "Users"
Expand Down Expand Up @@ -103,7 +108,7 @@ func (m *managerService) listenPipe() error {
go func() {
peer := conn.RemoteAddr().Network()
log.Debug().Msgf("Client connected: %s", peer)
m.handle(conn)
handle(conn)
if err := conn.Close(); err != nil {
log.Err(err).Msgf("Error closing connection for: %s", peer)
}
Expand Down
2 changes: 1 addition & 1 deletion supervisor/install/install_windows.go
Expand Up @@ -76,7 +76,7 @@ func Uninstall() error {
}

func installAndStartService(m *mgr.Mgr, name string, options Options, config mgr.Config) error {
s, err := m.CreateService(name, options.SupervisorPath, config, "")
s, err := m.CreateService(name, options.SupervisorPath, config, "-winservice")
if err != nil {
return fmt.Errorf("could not create service: %w", err)
}
Expand Down
39 changes: 39 additions & 0 deletions supervisor/svflags/flags.go
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package svflags

import (
"flag"

"github.com/rs/zerolog"
)

// Supervisor CLI flags.
var (
FlagVersion = flag.Bool("version", false, "Print version")
FlagInstall = flag.Bool("install", false, "Install or repair myst supervisor")
FlagUninstall = flag.Bool("uninstall", false, "Uninstall myst supervisor")
FlagLogFilePath = flag.String("log-path", "", "Supervisor log file path")
FlagLogLevel = flag.String("log-level", zerolog.InfoLevel.String(), "Logging level")
FlagWinService = flag.Bool("winservice", false, "Run via service manager instead of standalone (windows only).")
)

// Parse parses supervisor flags.
func Parse() {
flag.Parse()
}