Skip to content

Commit

Permalink
feature: support client command line argument
Browse files Browse the repository at this point in the history
The client mount options can be obtained from both config file and
command line arguments. Note that the priority of command line argument is
higher than that of config file, and will overwrite the corresponding
field.

Signed-off-by: Shuoran Liu <[email protected]>
  • Loading branch information
shuoranliu committed Mar 13, 2020
1 parent 7fcd69b commit baf507d
Show file tree
Hide file tree
Showing 3 changed files with 259 additions and 124 deletions.
110 changes: 57 additions & 53 deletions client/fuse.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
"path"
"path/filepath"
"runtime"
"strconv"
"strings"
"syscall"

Expand Down Expand Up @@ -77,6 +76,13 @@ var (
configForeground = flag.Bool("f", false, "run foreground")
)

var GlobalMountOptions []proto.MountOption

func init() {
GlobalMountOptions = proto.NewMountOptions()
proto.InitMountOptions(GlobalMountOptions)
}

func main() {
runtime.GOMAXPROCS(runtime.NumCPU())

Expand All @@ -90,16 +96,6 @@ func main() {
os.Exit(0)
}

/*
* LoadConfigFile should be checked before start daemon, since it will
* call os.Exit() w/o notifying the parent process.
*/
cfg, err := config.LoadConfigFile(*configFile)
if err != nil {
daemonize.SignalOutcome(err)
os.Exit(1)
}

if !*configForeground {
if err := startDaemon(); err != nil {
fmt.Printf("Mount failed: %v\n", err)
Expand All @@ -113,6 +109,7 @@ func main() {
* Must notify the parent process through SignalOutcome anyway.
*/

cfg, _ := config.LoadConfigFile(*configFile)
opt, err := parseMountOption(cfg)
if err != nil {
daemonize.SignalOutcome(err)
Expand Down Expand Up @@ -141,6 +138,12 @@ func main() {
}()
syslog.SetOutput(outputFile)

syslog.Println("*** Final Mount Options ***")
for _, o := range GlobalMountOptions {
syslog.Println(o)
}
syslog.Println("*** End ***")

if err = sysutil.RedirectFD(int(outputFile.Fd()), int(os.Stderr.Fd())); err != nil {
daemonize.SignalOutcome(err)
os.Exit(1)
Expand Down Expand Up @@ -181,14 +184,26 @@ func startDaemon() error {
return fmt.Errorf("startDaemon failed: cannot get absolute command path, err(%v)", err)
}

configPath, err := filepath.Abs(*configFile)
if err != nil {
return fmt.Errorf("startDaemon failed: cannot get absolute command path of config file(%v) , err(%v)", *configFile, err)
if len(os.Args) <= 1 {
return fmt.Errorf("startDaemon failed: cannot use null arguments")
}

args := []string{"-f"}
args = append(args, "-c")
args = append(args, configPath)
args = append(args, os.Args[1:]...)

if *configFile != "" {
configPath, err := filepath.Abs(*configFile)
if err != nil {
return fmt.Errorf("startDaemon failed: cannot get absolute command path of config file(%v) , err(%v)", *configFile, err)
}
for i := 0; i < len(args); i++ {
if args[i] == "-c" {
// Since *configFile is not "", the (i+1)th argument must be the config file path
args[i+1] = configPath
break
}
}
}

env := []string{
fmt.Sprintf("PATH=%s", os.Getenv("PATH")),
Expand Down Expand Up @@ -254,37 +269,39 @@ func parseMountOption(cfg *config.Config) (*proto.MountOptions, error) {
var err error
opt := new(proto.MountOptions)

rawmnt := cfg.GetString(proto.MountPoint)
proto.ParseMountOptions(GlobalMountOptions, cfg)

rawmnt := GlobalMountOptions[proto.MountPoint].GetString()
opt.MountPoint, err = filepath.Abs(rawmnt)
if err != nil {
return nil, errors.Trace(err, "invalide mount point (%v) ", rawmnt)
}

opt.Volname = cfg.GetString(proto.VolName)
opt.Owner = cfg.GetString(proto.Owner)
opt.Master = cfg.GetString(proto.MasterAddr)
opt.Logpath = cfg.GetString(proto.LogDir)
opt.Loglvl = cfg.GetString(proto.LogLevel)
opt.Profport = cfg.GetString(proto.ProfPort)
opt.IcacheTimeout = parseConfigString(cfg, proto.IcacheTimeout)
opt.LookupValid = parseConfigString(cfg, proto.LookupValid)
opt.AttrValid = parseConfigString(cfg, proto.AttrValid)
opt.ReadRate = parseConfigString(cfg, proto.ReadRate)
opt.WriteRate = parseConfigString(cfg, proto.WriteRate)
opt.EnSyncWrite = parseConfigString(cfg, proto.EnSyncWrite)
opt.AutoInvalData = parseConfigString(cfg, proto.AutoInvalData)
opt.UmpDatadir = cfg.GetString(proto.WarnLogDir)
opt.Rdonly = cfg.GetBool(proto.Rdonly)
opt.WriteCache = cfg.GetBool(proto.WriteCache)
opt.KeepCache = cfg.GetBool(proto.KeepCache)
opt.FollowerRead = cfg.GetBool(proto.FollowerRead)
opt.Authenticate = cfg.GetBool(proto.Authenticate)
opt.Volname = GlobalMountOptions[proto.VolName].GetString()
opt.Owner = GlobalMountOptions[proto.Owner].GetString()
opt.Master = GlobalMountOptions[proto.Master].GetString()
opt.Logpath = GlobalMountOptions[proto.LogDir].GetString()
opt.Loglvl = GlobalMountOptions[proto.LogLevel].GetString()
opt.Profport = GlobalMountOptions[proto.ProfPort].GetString()
opt.IcacheTimeout = GlobalMountOptions[proto.IcacheTimeout].GetInt64()
opt.LookupValid = GlobalMountOptions[proto.LookupValid].GetInt64()
opt.AttrValid = GlobalMountOptions[proto.AttrValid].GetInt64()
opt.ReadRate = GlobalMountOptions[proto.ReadRate].GetInt64()
opt.WriteRate = GlobalMountOptions[proto.WriteRate].GetInt64()
opt.EnSyncWrite = GlobalMountOptions[proto.EnSyncWrite].GetInt64()
opt.AutoInvalData = GlobalMountOptions[proto.AutoInvalData].GetInt64()
opt.UmpDatadir = GlobalMountOptions[proto.WarnLogDir].GetString()
opt.Rdonly = GlobalMountOptions[proto.Rdonly].GetBool()
opt.WriteCache = GlobalMountOptions[proto.WriteCache].GetBool()
opt.KeepCache = GlobalMountOptions[proto.KeepCache].GetBool()
opt.FollowerRead = GlobalMountOptions[proto.FollowerRead].GetBool()
opt.Authenticate = GlobalMountOptions[proto.Authenticate].GetBool()
if opt.Authenticate {
opt.TicketMess.ClientKey = cfg.GetString(proto.ClientKey)
opt.TicketMess.TicketHost = cfg.GetString(proto.TicketHost)
opt.TicketMess.EnableHTTPS = cfg.GetBool(proto.EnableHTTPS)
opt.TicketMess.ClientKey = GlobalMountOptions[proto.ClientKey].GetString()
opt.TicketMess.TicketHost = GlobalMountOptions[proto.TicketHost].GetString()
opt.TicketMess.EnableHTTPS = GlobalMountOptions[proto.EnableHTTPS].GetBool()
if opt.TicketMess.EnableHTTPS {
opt.TicketMess.CertFile = cfg.GetString(proto.CertFile)
opt.TicketMess.CertFile = GlobalMountOptions[proto.CertFile].GetString()
}
}

Expand All @@ -295,19 +312,6 @@ func parseMountOption(cfg *config.Config) (*proto.MountOptions, error) {
return opt, nil
}

func parseConfigString(cfg *config.Config, keyword string) int64 {
var ret int64 = -1
rawstr := cfg.GetString(keyword)
if rawstr != "" {
val, err := strconv.Atoi(rawstr)
if err == nil {
ret = int64(val)
fmt.Println(fmt.Sprintf("keyword[%v] value[%v]", keyword, ret))
}
}
return ret
}

func parseLogLevel(loglvl string) log.Level {
var level log.Level
switch strings.ToLower(loglvl) {
Expand Down
87 changes: 40 additions & 47 deletions clientv2/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import (
"path"
"path/filepath"
"runtime"
"strconv"
"strings"
"syscall"

Expand Down Expand Up @@ -78,6 +77,13 @@ var (
configForeground = flag.Bool("f", false, "run foreground")
)

var GlobalMountOptions []proto.MountOption

func init() {
GlobalMountOptions = proto.NewMountOptions()
proto.InitMountOptions(GlobalMountOptions)
}

func main() {
runtime.GOMAXPROCS(runtime.NumCPU())

Expand All @@ -91,16 +97,6 @@ func main() {
os.Exit(0)
}

/*
* LoadConfigFile should be checked before start daemon, since it will
* call os.Exit() w/o notifying the parent process.
*/
cfg, err := config.LoadConfigFile(*configFile)
if err != nil {
daemonize.SignalOutcome(err)
os.Exit(1)
}

if !*configForeground {
if err := startDaemon(); err != nil {
fmt.Printf("Mount failed: %v\n", err)
Expand All @@ -114,6 +110,7 @@ func main() {
* Must notify the parent process through SignalOutcome anyway.
*/

cfg, _ := config.LoadConfigFile(*configFile)
opt, err := parseMountOption(cfg)
if err != nil {
daemonize.SignalOutcome(err)
Expand Down Expand Up @@ -142,6 +139,12 @@ func main() {
}()
syslog.SetOutput(outputFile)

syslog.Println("*** Final Mount Options ***")
for _, o := range GlobalMountOptions {
syslog.Println(o)
}
syslog.Println("*** End ***")

if err = sysutil.RedirectFD(int(outputFile.Fd()), int(os.Stderr.Fd())); err != nil {
daemonize.SignalOutcome(err)
os.Exit(1)
Expand Down Expand Up @@ -246,36 +249,39 @@ func parseMountOption(cfg *config.Config) (*proto.MountOptions, error) {
opt := new(proto.MountOptions)
opt.Config = cfg

rawmnt := cfg.GetString(proto.MountPoint)
proto.ParseMountOptions(GlobalMountOptions, cfg)

rawmnt := GlobalMountOptions[proto.MountPoint].GetString()
opt.MountPoint, err = filepath.Abs(rawmnt)
if err != nil {
return nil, errors.Trace(err, "invalide mount point (%v) ", rawmnt)
}

opt.Volname = cfg.GetString(proto.VolName)
opt.Owner = cfg.GetString(proto.Owner)
opt.Master = cfg.GetString(proto.MasterAddr)
opt.Logpath = cfg.GetString(proto.LogDir)
opt.Loglvl = cfg.GetString(proto.LogLevel)
opt.Profport = cfg.GetString(proto.ProfPort)
opt.IcacheTimeout = parseConfigString(cfg, proto.IcacheTimeout)
opt.LookupValid = parseConfigString(cfg, proto.LookupValid)
opt.AttrValid = parseConfigString(cfg, proto.AttrValid)
opt.ReadRate = parseConfigString(cfg, proto.ReadRate)
opt.WriteRate = parseConfigString(cfg, proto.WriteRate)
opt.EnSyncWrite = parseConfigString(cfg, proto.EnSyncWrite)
opt.UmpDatadir = cfg.GetString(proto.WarnLogDir)
opt.Rdonly = cfg.GetBool(proto.Rdonly)
opt.WriteCache = cfg.GetBool(proto.WriteCache)
opt.KeepCache = cfg.GetBool(proto.KeepCache)
opt.FollowerRead = cfg.GetBool(proto.FollowerRead)
opt.Authenticate = cfg.GetBool(proto.Authenticate)
opt.Volname = GlobalMountOptions[proto.VolName].GetString()
opt.Owner = GlobalMountOptions[proto.Owner].GetString()
opt.Master = GlobalMountOptions[proto.Master].GetString()
opt.Logpath = GlobalMountOptions[proto.LogDir].GetString()
opt.Loglvl = GlobalMountOptions[proto.LogLevel].GetString()
opt.Profport = GlobalMountOptions[proto.ProfPort].GetString()
opt.IcacheTimeout = GlobalMountOptions[proto.IcacheTimeout].GetInt64()
opt.LookupValid = GlobalMountOptions[proto.LookupValid].GetInt64()
opt.AttrValid = GlobalMountOptions[proto.AttrValid].GetInt64()
opt.ReadRate = GlobalMountOptions[proto.ReadRate].GetInt64()
opt.WriteRate = GlobalMountOptions[proto.WriteRate].GetInt64()
opt.EnSyncWrite = GlobalMountOptions[proto.EnSyncWrite].GetInt64()
opt.AutoInvalData = GlobalMountOptions[proto.AutoInvalData].GetInt64()
opt.UmpDatadir = GlobalMountOptions[proto.WarnLogDir].GetString()
opt.Rdonly = GlobalMountOptions[proto.Rdonly].GetBool()
opt.WriteCache = GlobalMountOptions[proto.WriteCache].GetBool()
opt.KeepCache = GlobalMountOptions[proto.KeepCache].GetBool()
opt.FollowerRead = GlobalMountOptions[proto.FollowerRead].GetBool()
opt.Authenticate = GlobalMountOptions[proto.Authenticate].GetBool()
if opt.Authenticate {
opt.TicketMess.ClientKey = cfg.GetString(proto.ClientKey)
opt.TicketMess.TicketHost = cfg.GetString(proto.TicketHost)
opt.TicketMess.EnableHTTPS = cfg.GetBool(proto.EnableHTTPS)
opt.TicketMess.ClientKey = GlobalMountOptions[proto.ClientKey].GetString()
opt.TicketMess.TicketHost = GlobalMountOptions[proto.TicketHost].GetString()
opt.TicketMess.EnableHTTPS = GlobalMountOptions[proto.EnableHTTPS].GetBool()
if opt.TicketMess.EnableHTTPS {
opt.TicketMess.CertFile = cfg.GetString(proto.CertFile)
opt.TicketMess.CertFile = GlobalMountOptions[proto.CertFile].GetString()
}
}

Expand All @@ -286,19 +292,6 @@ func parseMountOption(cfg *config.Config) (*proto.MountOptions, error) {
return opt, nil
}

func parseConfigString(cfg *config.Config, keyword string) int64 {
var ret int64 = -1
rawstr := cfg.GetString(keyword)
if rawstr != "" {
val, err := strconv.Atoi(rawstr)
if err == nil {
ret = int64(val)
fmt.Println(fmt.Sprintf("keyword[%v] value[%v]", keyword, ret))
}
}
return ret
}

// ParseLogLevel returns the log level based on the given string.
func parseLogLevel(loglvl string) log.Level {
var level log.Level
Expand Down
Loading

0 comments on commit baf507d

Please sign in to comment.