Move proc locking into entrypoint

This completely cleans up all logic that used to be in crypticnet.
This commit is contained in:
Brian Picciano 2022-10-27 00:45:40 +02:00
parent 28159608c8
commit b26f4bdd6a
5 changed files with 41 additions and 79 deletions

View File

@ -2,7 +2,6 @@ package main
import ( import (
"context" "context"
crypticnet "cryptic-net"
"cryptic-net/admin" "cryptic-net/admin"
"cryptic-net/bootstrap" "cryptic-net/bootstrap"
"cryptic-net/daemon" "cryptic-net/daemon"
@ -103,29 +102,11 @@ var subCmdAdminCreateNetwork = subCmd{
return fmt.Errorf("invalid hostname %q: %w", *hostName, err) return fmt.Errorf("invalid hostname %q: %w", *hostName, err)
} }
adminCreationParams := admin.CreationParams{ runtimeDirCleanup, err := setupAndLockRuntimeDir()
ID: randStr(32), if err != nil {
Domain: *domain, return fmt.Errorf("setting up runtime directory: %w", err)
}
{
runtimeDirPath := envRuntimeDirPath
fmt.Fprintf(os.Stderr, "will use runtime directory %q for temporary state\n", runtimeDirPath)
if err := os.MkdirAll(runtimeDirPath, 0700); err != nil {
return fmt.Errorf("creating directory %q: %w", runtimeDirPath, err)
} else if err := crypticnet.NewProcLock(runtimeDirPath).WriteLock(); err != nil {
return err
}
defer func() {
fmt.Fprintf(os.Stderr, "cleaning up runtime directory %q\n", runtimeDirPath)
if err := os.RemoveAll(runtimeDirPath); err != nil {
fmt.Fprintf(os.Stderr, "error removing temporary directory %q: %v", runtimeDirPath, err)
}
}()
} }
defer runtimeDirCleanup()
daemonConfig, err := daemon.LoadConfig(envAppDirPath, *daemonConfigPath) daemonConfig, err := daemon.LoadConfig(envAppDirPath, *daemonConfigPath)
if err != nil { if err != nil {
@ -146,6 +127,11 @@ var subCmdAdminCreateNetwork = subCmd{
return fmt.Errorf("creating nebula cert for host: %w", err) return fmt.Errorf("creating nebula cert for host: %w", err)
} }
adminCreationParams := admin.CreationParams{
ID: randStr(32),
Domain: *domain,
}
hostBootstrap := bootstrap.Bootstrap{ hostBootstrap := bootstrap.Bootstrap{
AdminCreationParams: adminCreationParams, AdminCreationParams: adminCreationParams,
Hosts: map[string]bootstrap.Host{ Hosts: map[string]bootstrap.Host{

View File

@ -10,7 +10,6 @@ import (
"sync" "sync"
"time" "time"
crypticnet "cryptic-net"
"cryptic-net/bootstrap" "cryptic-net/bootstrap"
"cryptic-net/daemon" "cryptic-net/daemon"
"cryptic-net/garage" "cryptic-net/garage"
@ -236,26 +235,11 @@ var subCmdDaemon = subCmd{
return daemon.CopyDefaultConfig(os.Stdout, envAppDirPath) return daemon.CopyDefaultConfig(os.Stdout, envAppDirPath)
} }
runtimeDirPath := envRuntimeDirPath runtimeDirCleanup, err := setupAndLockRuntimeDir()
if err != nil {
fmt.Fprintf(os.Stderr, "will use runtime directory %q for temporary state\n", runtimeDirPath) return fmt.Errorf("setting up runtime directory: %w", err)
if err := os.MkdirAll(runtimeDirPath, 0700); err != nil {
return fmt.Errorf("creating directory %q: %w", runtimeDirPath, err)
} else if err := crypticnet.NewProcLock(runtimeDirPath).WriteLock(); err != nil {
return err
} }
defer runtimeDirCleanup()
// do not defer the cleaning of the runtime directory until the lock has
// been obtained, otherwise we might delete the directory out from under
// the feet of an already running daemon
defer func() {
fmt.Fprintf(os.Stderr, "cleaning up runtime directory %q\n", runtimeDirPath)
if err := os.RemoveAll(runtimeDirPath); err != nil {
fmt.Fprintf(os.Stderr, "error removing temporary directory %q: %v", runtimeDirPath, err)
}
}()
var ( var (
bootstrapDataDirPath = bootstrap.DataDirPath(envDataDirPath) bootstrapDataDirPath = bootstrap.DataDirPath(envDataDirPath)
@ -264,8 +248,6 @@ var subCmdDaemon = subCmd{
hostBootstrapPath string hostBootstrapPath string
hostBootstrap bootstrap.Bootstrap hostBootstrap bootstrap.Bootstrap
foundHostBootstrap bool foundHostBootstrap bool
err error
) )
tryLoadBootstrap := func(path string) bool { tryLoadBootstrap := func(path string) bool {

View File

@ -1,4 +1,4 @@
package crypticnet package main
import ( import (
"errors" "errors"
@ -12,33 +12,13 @@ import (
var errDaemonNotRunning = errors.New("no cryptic-net daemon process running") var errDaemonNotRunning = errors.New("no cryptic-net daemon process running")
// ProcLock is used to lock a process. func lockFilePath() string {
type ProcLock interface { return filepath.Join(envRuntimeDirPath, "lock")
// WriteLock creates a new lock, or errors if the lock is alread held.
WriteLock() error
// AssertLock returns an error if the lock already exists.
AssertLock() error
} }
type procLock struct { func writeLock() error {
dir string
}
// NewProcLock returns a ProcLock which will use a file in the given directory lockFilePath := lockFilePath()
// to lock the process.
func NewProcLock(dir string) ProcLock {
return &procLock{dir: dir}
}
func (pl *procLock) path() string {
return filepath.Join(pl.dir, "lock")
}
func (pl *procLock) WriteLock() error {
lockFilePath := pl.path()
lockFile, err := os.OpenFile( lockFile, err := os.OpenFile(
lockFilePath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0400, lockFilePath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0400,
@ -63,11 +43,31 @@ func (pl *procLock) WriteLock() error {
return nil return nil
} }
// returns a cleanup function which will clean up the created runtime directory.
func setupAndLockRuntimeDir() (func(), error) {
fmt.Fprintf(os.Stderr, "will use runtime directory %q for temporary state\n", envRuntimeDirPath)
if err := os.MkdirAll(envRuntimeDirPath, 0700); err != nil {
return nil, fmt.Errorf("creating directory %q: %w", envRuntimeDirPath, err)
} else if err := writeLock(); err != nil {
return nil, err
}
return func() {
fmt.Fprintf(os.Stderr, "cleaning up runtime directory %q\n", envRuntimeDirPath)
if err := os.RemoveAll(envRuntimeDirPath); err != nil {
fmt.Fprintf(os.Stderr, "error removing temporary directory %q: %v", envRuntimeDirPath, err)
}
}, nil
}
// checks that the lock file exists and that the process which created it also // checks that the lock file exists and that the process which created it also
// still exists. // still exists.
func (pl *procLock) AssertLock() error { func assertLock() error {
lockFilePath := pl.path() lockFilePath := lockFilePath()
lockFile, err := os.Open(lockFilePath) lockFile, err := os.Open(lockFilePath)

View File

@ -2,7 +2,6 @@ package main
import ( import (
"context" "context"
crypticnet "cryptic-net"
"fmt" "fmt"
"os" "os"
"strings" "strings"
@ -101,9 +100,7 @@ func (ctx subCmdCtx) doSubCmd(subCmds ...subCmd) error {
if subCmd.checkLock { if subCmd.checkLock {
err := crypticnet.NewProcLock(envRuntimeDirPath).AssertLock() if err := assertLock(); err != nil {
if err != nil {
return fmt.Errorf("checking lock file: %w", err) return fmt.Errorf("checking lock file: %w", err)
} }
} }

View File

@ -1,3 +0,0 @@
// Package globals defines global constants and variables which are valid
// across all cryptic-net processes and sub-processes.
package crypticnet