Commit e3ff9f3a authored by zdc's avatar zdc

many fixes

* fix template to validity for https://validator.w3.org/
* changed action validation (no need to hardcode action now)
* added ability to create new commands with simply adding line to config (need template change!)
* added JSON output with routers and command list (for future needs)
parent 816e6007
...@@ -10,9 +10,9 @@ address = "127.0.0.1" ...@@ -10,9 +10,9 @@ address = "127.0.0.1"
port = "22" port = "22"
user = "lookis" user = "lookis"
password = "" password = ""
ping_command = "ping count 5" command_ping = "ping count 5"
traceroute_command = "traceroute as-number-lookup no-resolve" command_traceroute = "traceroute as-number-lookup no-resolve"
showroute_command = "show route all" command_showroute = "show route all"
[router02] [router02]
enabled = "yes" enabled = "yes"
...@@ -22,10 +22,10 @@ address = "127.0.0.2" ...@@ -22,10 +22,10 @@ address = "127.0.0.2"
port = "22" port = "22"
user = "lookis" user = "lookis"
password = "" password = ""
ping_command = "/opt/vyatta/bin/ping" command_ping = "/opt/vyatta/bin/ping"
ping_command_suffix = "count 5" command_ping_suffix = "count 5"
traceroute_command = "traceroute" command_traceroute = "traceroute"
showroute_command = "/opt/vyatta/bin/vtyshow.pl show ip route" command_showroute = "/opt/vyatta/bin/vtyshow.pl show ip route"
[router03] [router03]
enabled = "no" enabled = "no"
...@@ -35,7 +35,7 @@ address = "127.0.0.3" ...@@ -35,7 +35,7 @@ address = "127.0.0.3"
port = "22" port = "22"
user = "lookis" user = "lookis"
password = "" password = ""
ping_command = "ping count=5" command_ping = "ping count=5"
traceroute_command = "tool traceroute count=1" command_traceroute = "tool traceroute count=1"
showroute_command = "ip route print where" command_showroute = "ip route print where"
showroute_command_suffix = "in dst-address and active" command_showroute_suffix = "in dst-address and active"
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"flag" "flag"
"fmt" "fmt"
"html/template" "html/template"
"encoding/json"
"log" "log"
"net" "net"
"net/http" "net/http"
...@@ -14,30 +15,34 @@ import ( ...@@ -14,30 +15,34 @@ import (
) )
// setting global variables // setting global variables
var AllConfigKeys []string
var datapath string var datapath string
var RouterList []Routers var RouterList []Router
// declare type for routers list // declare type for routers list
type Routers struct { type Router struct {
RouterId, RouterName string RouterId, RouterName string
RouterCommands []string
} }
// declare variables for page template // declare variables for page template
type DataOut struct { type DataOut struct {
RoutersList []Routers RoutersList []Router
OutputHeader, OutputBody string OutputHeader, OutputBody string
} }
// fill error details // fill error details
func PrepareError (RoutersRaw []Routers, HeaderRaw, BodyRaw string) DataOut { func PrepareError (RoutersRaw []Router, HeaderRaw, BodyRaw string) DataOut {
log.Printf("Error! %s: \"%s\"", HeaderRaw, BodyRaw) log.Printf("Error! %s: \"%s\"", HeaderRaw, BodyRaw)
output := DataOut{ RoutersList: RoutersRaw, OutputHeader: HeaderRaw, OutputBody: BodyRaw } output := DataOut{ RoutersList: RoutersRaw, OutputHeader: HeaderRaw, OutputBody: BodyRaw }
return output return output
} }
// fill normal output // fill normal output
func PrepareOutput (RoutersRaw []Routers, HeaderRaw, BodyRaw string) DataOut { func PrepareOutput (RoutersRaw []Router, HeaderRaw, BodyRaw string) DataOut {
output := DataOut{ RoutersList: RoutersRaw, OutputHeader: HeaderRaw, OutputBody: BodyRaw } output := DataOut{ RoutersList: RoutersRaw, OutputHeader: HeaderRaw, OutputBody: BodyRaw }
return output return output
} }
...@@ -45,36 +50,25 @@ func PrepareOutput (RoutersRaw []Routers, HeaderRaw, BodyRaw string) DataOut { ...@@ -45,36 +50,25 @@ func PrepareOutput (RoutersRaw []Routers, HeaderRaw, BodyRaw string) DataOut {
func ByteToString (byteinput []byte) string { func ByteToString (byteinput []byte) string {
byteslen := len(byteinput) byteslen := len(byteinput)
stringoutput := string(byteinput[:byteslen]) stringoutput := string(byteinput[:byteslen])
return stringoutput return stringoutput
} }
// check for correct action // check for correct action and return command for it
func CheckCommand (command string) bool { func GetCommand (router, command string) (string, bool) {
switch command { var AvalList []string
case "ping": var Command string
return true var CommandState bool
case "traceroute":
return true
case "showroute":
return true
default:
return false
}
}
// select command from list AvalList = GetRouterCommands(router)
func SelectCommand (command, ping_command, traceroute_command, showroute_command string) string { for i := range AvalList {
switch command { if AvalList[i] == command {
case "ping": Command = viper.GetString(router+".command_"+command)
command = ping_command CommandState = true
case "traceroute": }
command = traceroute_command
case "showroute":
command = showroute_command
default:
command = ""
} }
return command
return Command, CommandState
} }
// connect to router and run command // connect to router and run command
...@@ -120,37 +114,59 @@ func SSHRun (router_ip, port, username, password, command, argument, suffix stri ...@@ -120,37 +114,59 @@ func SSHRun (router_ip, port, username, password, command, argument, suffix stri
} }
} }
} }
return output return output
} }
// get router name from config file // get router name from config file
func GetRouterName (RouterId string) string { func GetRouterName (RouterId string) string {
var RouterName string var RouterName string
RouterName = viper.GetString(RouterId+".name") RouterName = viper.GetString(RouterId+".name")
return RouterName return RouterName
} }
// get command list for router from config file
func GetRouterCommands (RouterId string) []string {
var CommandList []string
for i := range AllConfigKeys {
// find those, who match RouterId.command_XXX
matchstring := RouterId+`.command_\w*[^(suffix)]$`
matched, _ := regexp.MatchString(matchstring, AllConfigKeys[i])
if matched == true {
//get command name
var strip = regexp.MustCompile(RouterId+".command_")
command := strip.ReplaceAllString(AllConfigKeys[i], "")
CommandList = append(CommandList, command)
}
}
return CommandList
}
// parse enabled router list from config // parse enabled router list from config
func ParseRoutersFromConfig (enabled string) []Routers { func ParseRoutersFromConfig () []Router {
var allkeys []string var routers []Router
var routers []Routers var enabled string
// get all keys from config enabled = `router[\d]*.enabled`
allkeys = viper.AllKeys() for i := range AllConfigKeys {
sort.Strings(allkeys)
for i := range allkeys {
// find those, who match routerNN.enabled // find those, who match routerNN.enabled
matched, _ := regexp.MatchString(enabled, allkeys[i]) matched, _ := regexp.MatchString(enabled, AllConfigKeys[i])
if matched == true { if matched == true {
//check if enabled = "yes" //check if enabled = "yes"
var strip = regexp.MustCompile(`\.enabled`) var strip = regexp.MustCompile(`\.enabled`)
routerid := strip.ReplaceAllString(allkeys[i], "") routerid := strip.ReplaceAllString(AllConfigKeys[i], "")
if viper.GetString(routerid+".enabled") == "yes" { if viper.GetString(routerid+".enabled") == "yes" {
routername := GetRouterName(routerid) routername := GetRouterName(routerid)
routers = append(routers, Routers { RouterId: routerid, RouterName: routername }) commandlist := GetRouterCommands(routerid)
routers = append(routers, Router { RouterId: routerid, RouterName: routername, RouterCommands: commandlist })
} }
} }
} }
return routers return routers
} }
...@@ -160,11 +176,11 @@ func ShowPage (w http.ResponseWriter, r *http.Request) { ...@@ -160,11 +176,11 @@ func ShowPage (w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles(datapath+"/page_main.gtpl") t, _ := template.ParseFiles(datapath+"/page_main.gtpl")
// check HTTP method // check HTTP method
if r.Method == "POST" { if r.Method == "POST" {
var action, argument string var Command, argument, suffix string
var router_ip, port, username, password string var router_ip, port, username, password string
var ping_command, traceroute_command, showroute_command, command, suffix string
var output DataOut var output DataOut
var allok bool = true var allok bool = true
var CommandState bool
// get POST data // get POST data
input_router := r.PostFormValue("router") input_router := r.PostFormValue("router")
...@@ -181,18 +197,13 @@ func ShowPage (w http.ResponseWriter, r *http.Request) { ...@@ -181,18 +197,13 @@ func ShowPage (w http.ResponseWriter, r *http.Request) {
port = viper.GetString(input_router+".port") port = viper.GetString(input_router+".port")
username = viper.GetString(input_router+".user") username = viper.GetString(input_router+".user")
password = viper.GetString(input_router+".password") password = viper.GetString(input_router+".password")
ping_command = viper.GetString(input_router+".ping_command")
traceroute_command = viper.GetString(input_router+".traceroute_command")
showroute_command = viper.GetString(input_router+".showroute_command")
} }
// check for selected action // check and get command for selected action
if CheckCommand(input_action) == false { Command, CommandState = GetCommand(input_router, input_action)
if CommandState == false {
output = PrepareError (RouterList, "Bad command", input_action) output = PrepareError (RouterList, "Bad command", input_action)
allok = false allok = false
} else {
action = input_action
} }
// check for argument // check for argument
...@@ -205,12 +216,11 @@ func ShowPage (w http.ResponseWriter, r *http.Request) { ...@@ -205,12 +216,11 @@ func ShowPage (w http.ResponseWriter, r *http.Request) {
// connect to router and run command // connect to router and run command
if allok == true { if allok == true {
command = SelectCommand(action, ping_command, traceroute_command, showroute_command)
// check if command need suffix // check if command need suffix
if viper.IsSet(input_router+"."+action+"_command_suffix") != false { if viper.IsSet(input_router+".command_"+input_action+"_suffix") != false {
suffix = " "+viper.GetString(input_router+"."+action+"_command_suffix") suffix = " "+viper.GetString(input_router+".command_"+input_action+"_suffix")
} }
output = SSHRun(router_ip, port, username, password, command, argument, suffix) output = SSHRun(router_ip, port, username, password, Command, argument, suffix)
// show result to user // show result to user
t.Execute(w, output) t.Execute(w, output)
} else { } else {
...@@ -224,6 +234,12 @@ func ShowPage (w http.ResponseWriter, r *http.Request) { ...@@ -224,6 +234,12 @@ func ShowPage (w http.ResponseWriter, r *http.Request) {
} }
} }
// show JSON with routers and commands
func ShowJSON (w http.ResponseWriter, r *http.Request) {
jsonout, _ := json.MarshalIndent(ParseRoutersFromConfig(), "", "\t")
w.Write(jsonout)
}
func main() { func main() {
// set config // set config
flag.StringVar(&datapath, "data", "", "data directory") flag.StringVar(&datapath, "data", "", "data directory")
...@@ -240,13 +256,18 @@ func main() { ...@@ -240,13 +256,18 @@ func main() {
panic(fmt.Errorf("Fatal error config file: %s \n", errconfig)) panic(fmt.Errorf("Fatal error config file: %s \n", errconfig))
} }
// get all keys from config (used next in program)
AllConfigKeys = viper.AllKeys()
sort.Strings(AllConfigKeys)
// read router list from config // read router list from config
RouterList = ParseRoutersFromConfig(`router[\d]*.enabled`) RouterList = ParseRoutersFromConfig()
// set http server variables // set http server variables
server_address := viper.GetString("server.address") server_address := viper.GetString("server.address")
server_port := viper.GetString("server.port") server_port := viper.GetString("server.port")
http.HandleFunc("/", ShowPage) http.HandleFunc("/", ShowPage)
http.HandleFunc("/json", ShowJSON)
// run server // run server
fmt.Println("lookis started") fmt.Println("lookis started")
......
<!DOCTYPE html>
<html> <html>
<head> <head>
<title>Looking Glass</title> <title>Looking Glass</title>
...@@ -37,7 +38,7 @@ ...@@ -37,7 +38,7 @@
<tr> <tr>
<td>Argument</td> <td>Argument</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td><input name="argument" type="input" /></td> <td><input name="argument" type="text" /></td>
</tr> </tr>
<tr> <tr>
<td style="text-align: center;" colspan="3"> <td style="text-align: center;" colspan="3">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment