Skip to content

Commit

Permalink
Rewrite yanic command
Browse files Browse the repository at this point in the history
  • Loading branch information
corny committed Sep 17, 2017
1 parent b5a694a commit 3ecd21a
Show file tree
Hide file tree
Showing 8 changed files with 289 additions and 108 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ install:
script:
- ./.test-coverage
- go install github.com/FreifunkBremen/yanic/cmd/yanic
- go install github.com/FreifunkBremen/yanic/cmd/yanic-query
48 changes: 46 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,54 @@ Recently seen nodes that does not reply are requested via a unicast message.
## Quick startup

### Usage

Run Yanic without any arguments to get the usage information:

```
Usage: yanic [--version] [--help] <command> [<args>]
Available commands are:
import Import global statistics from the given RRD file, requires influxdb
query Emit a respondd query and display the responses
server Run as server
```

#### Server

```
yanic server [<args>]
Available arguments are:
-config string
path of configuration file (default "config.toml")
-timestamps
print timestamps in output (default true)
```

#### Import

```
yanic import [<args>] <file.rrd>
Available arguments are:
-config string
path of configuration file (default "config.toml")
-timestamps
print timestamps in output (default true)
```
Usage of ./yanic:
-config path/to/config.toml


#### Query

```
yanic query <iface> <dstaddress>
```

Example:
```
yanic-query wlp4s0 "[fe80::eade:27ff:dead:beef%wlp4s0]:1001"
```

### Configuration
Read comments in [config_example.toml](config_example.toml) for more information.

Expand Down
32 changes: 0 additions & 32 deletions cmd/yanic-query/main.go

This file was deleted.

36 changes: 36 additions & 0 deletions cmd/yanic/base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package main

import (
"flag"
"log"

"github.com/FreifunkBremen/yanic/runtime"
"github.com/mitchellh/cli"
)

type BaseCommand struct {
UI cli.Ui
flags *flag.FlagSet

configPath string
timestamps bool
}

func (c *BaseCommand) initFlags() {
c.flags = flag.NewFlagSet("", flag.ExitOnError)
c.flags.StringVar(&c.configPath, "config", "config.toml", "path of configuration file")
c.flags.BoolVar(&c.timestamps, "timestamps", true, "print timestamps in output")
}

func (c *BaseCommand) loadConfig() *runtime.Config {
if !c.timestamps {
log.SetFlags(0)
}

config, err := runtime.ReadConfigFile(c.configPath)
if err != nil {
panic(err)
}

return config
}
49 changes: 49 additions & 0 deletions cmd/yanic/import.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package main

import (
"log"

"github.com/FreifunkBremen/yanic/rrd"
"github.com/FreifunkBremen/yanic/runtime"
)

type ImportCommand struct {
BaseCommand
}

func (c *ImportCommand) Run(args []string) int {
c.initFlags()
if err := c.flags.Parse(args); err != nil {
return 1
}

c.loadConfig()

path := c.flags.Arg(0)
if path == "" {
return 2
}

log.Println("importing RRD from", path)

for ds := range rrd.Read(path) {
connections.InsertGlobals(
&runtime.GlobalStats{
Nodes: uint32(ds.Nodes),
Clients: uint32(ds.Clients),
},
ds.Time,
)
}
return 0
}

func (c *ImportCommand) Help() string {
c.initFlags()
c.flags.PrintDefaults()
return ""
}

func (c *ImportCommand) Synopsis() string {
return "Import global statistics from the given RRD file, requires influxdb"
}
102 changes: 29 additions & 73 deletions cmd/yanic/main.go
Original file line number Diff line number Diff line change
@@ -1,100 +1,56 @@
package main

import (
"flag"
"log"
"os"
"os/signal"
"syscall"
"time"

"github.com/FreifunkBremen/yanic/database"
"github.com/FreifunkBremen/yanic/database/all"
"github.com/FreifunkBremen/yanic/meshviewer"
"github.com/FreifunkBremen/yanic/respond"
"github.com/FreifunkBremen/yanic/rrd"
"github.com/FreifunkBremen/yanic/runtime"
"github.com/FreifunkBremen/yanic/webserver"
"github.com/mitchellh/cli"
)

var (
configFile string
config *runtime.Config
// Version is the build version
Version = "undefined"

collector *respond.Collector
connections database.Connection
nodes *runtime.Nodes
)

func main() {
var importPath string
var timestamps bool
flag.StringVar(&importPath, "import", "", "import global statistics from the given RRD file, requires influxdb")
flag.StringVar(&configFile, "config", "config.toml", "path of configuration file (default:config.yaml)")
flag.BoolVar(&timestamps, "timestamps", true, "print timestamps in output")
flag.Parse()
c := cli.NewCLI("yanic", Version)
c.Args = os.Args[1:]

if !timestamps {
log.SetFlags(0)
ui := &cli.BasicUi{
Reader: os.Stdin,
Writer: os.Stdout,
ErrorWriter: os.Stderr,
}
log.Println("Yanic say hello")

config, err := runtime.ReadConfigFile(configFile)
if err != nil {
panic(err)
c.Commands = map[string]cli.CommandFactory{
"server": func() (cli.Command, error) {
return &ServerCommand{
BaseCommand: BaseCommand{UI: ui},
}, nil
},
"import": func() (cli.Command, error) {
return &ImportCommand{
BaseCommand: BaseCommand{UI: ui},
}, nil
},
"query": func() (cli.Command, error) {
return &QueryCommand{
UI: ui,
}, nil
},
}

connections, err = all.Connect(config.Database.Connection)
exitStatus, err := c.Run()
if err != nil {
panic(err)
}
database.Start(connections, config)
defer database.Close(connections)

if connections != nil && importPath != "" {
importRRD(importPath)
return
}

nodes = runtime.NewNodes(config)
nodes.Start()
meshviewer.Start(config, nodes)

if config.Webserver.Enable {
log.Println("starting webserver on", config.Webserver.Bind)
srv := webserver.New(config.Webserver.Bind, config.Webserver.Webroot)
go srv.Close()
log.Println(err)
}

if config.Respondd.Enable {
// Delaying startup to start at a multiple of `duration` since the zero time.
if duration := config.Respondd.Synchronize.Duration; duration > 0 {
now := time.Now()
delay := duration - now.Sub(now.Truncate(duration))
log.Printf("delaying %0.1f seconds", delay.Seconds())
time.Sleep(delay)
}

collector = respond.NewCollector(connections, nodes, config.Respondd.Interface, config.Respondd.Port)
collector.Start(config.Respondd.CollectInterval.Duration)
defer collector.Close()
}

// Wait for INT/TERM
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
sig := <-sigs
log.Println("received", sig)
}

func importRRD(path string) {
log.Println("importing RRD from", path)
for ds := range rrd.Read(path) {
connections.InsertGlobals(
&runtime.GlobalStats{
Nodes: uint32(ds.Nodes),
Clients: uint32(ds.Clients),
},
ds.Time,
)
}
os.Exit(exitStatus)
}
51 changes: 51 additions & 0 deletions cmd/yanic/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package main

import (
"flag"
"log"
"net"
"time"

"github.com/FreifunkBremen/yanic/respond"
"github.com/FreifunkBremen/yanic/runtime"
"github.com/mitchellh/cli"
)

type QueryCommand struct {
UI cli.Ui
flags *flag.FlagSet
}

func (c *QueryCommand) Run(args []string) int {
if len(args) != 2 {
c.UI.Output(c.Synopsis())
return 1
}

iface := args[0]
dstAddress := args[1]

log.Printf("Sending request address=%s iface=%s", dstAddress, iface)

nodes := runtime.NewNodes(&runtime.Config{})

collector := respond.NewCollector(nil, nodes, iface, 0)
defer collector.Close()
collector.SendPacket(net.ParseIP(dstAddress))

time.Sleep(time.Second)

for id, data := range nodes.List {
log.Printf("%s: %+v", id, data)
}

return 0
}

func (c *QueryCommand) Help() string {
return "Emit a respondd query and display the responses"
}

func (c *QueryCommand) Synopsis() string {
return "Emit a respondd query and display the responses"
}

0 comments on commit 3ecd21a

Please sign in to comment.