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"
port = "22"
user = "lookis"
password = ""
ping_command = "ping count 5"
traceroute_command = "traceroute as-number-lookup no-resolve"
showroute_command = "show route all"
command_ping = "ping count 5"
command_traceroute = "traceroute as-number-lookup no-resolve"
command_showroute = "show route all"
[router02]
enabled = "yes"
......@@ -22,10 +22,10 @@ address = "127.0.0.2"
port = "22"
user = "lookis"
password = ""
ping_command = "/opt/vyatta/bin/ping"
ping_command_suffix = "count 5"
traceroute_command = "traceroute"
showroute_command = "/opt/vyatta/bin/vtyshow.pl show ip route"
command_ping = "/opt/vyatta/bin/ping"
command_ping_suffix = "count 5"
command_traceroute = "traceroute"
command_showroute = "/opt/vyatta/bin/vtyshow.pl show ip route"
[router03]
enabled = "no"
......@@ -35,7 +35,7 @@ address = "127.0.0.3"
port = "22"
user = "lookis"
password = ""
ping_command = "ping count=5"
traceroute_command = "tool traceroute count=1"
showroute_command = "ip route print where"
showroute_command_suffix = "in dst-address and active"
command_ping = "ping count=5"
command_traceroute = "tool traceroute count=1"
command_showroute = "ip route print where"
command_showroute_suffix = "in dst-address and active"
......@@ -4,6 +4,7 @@ import (
"flag"
"fmt"
"html/template"
"encoding/json"
"log"
"net"
"net/http"
......@@ -14,30 +15,34 @@ import (
)
// setting global variables
var AllConfigKeys []string
var datapath string
var RouterList []Routers
var RouterList []Router
// declare type for routers list
type Routers struct {
type Router struct {
RouterId, RouterName string
RouterCommands []string
}
// declare variables for page template
type DataOut struct {
RoutersList []Routers
RoutersList []Router
OutputHeader, OutputBody string
}
// 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)
output := DataOut{ RoutersList: RoutersRaw, OutputHeader: HeaderRaw, OutputBody: BodyRaw }
return 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 }
return output
}
......@@ -45,36 +50,25 @@ func PrepareOutput (RoutersRaw []Routers, HeaderRaw, BodyRaw string) DataOut {
func ByteToString (byteinput []byte) string {
byteslen := len(byteinput)
stringoutput := string(byteinput[:byteslen])
return stringoutput
}
// check for correct action
func CheckCommand (command string) bool {
switch command {
case "ping":
return true
case "traceroute":
return true
case "showroute":
return true
default:
return false
}
}
// check for correct action and return command for it
func GetCommand (router, command string) (string, bool) {
var AvalList []string
var Command string
var CommandState bool
// select command from list
func SelectCommand (command, ping_command, traceroute_command, showroute_command string) string {
switch command {
case "ping":
command = ping_command
case "traceroute":
command = traceroute_command
case "showroute":
command = showroute_command
default:
command = ""
AvalList = GetRouterCommands(router)
for i := range AvalList {
if AvalList[i] == command {
Command = viper.GetString(router+".command_"+command)
CommandState = true
}
}
return command
return Command, CommandState
}
// connect to router and run command
......@@ -120,37 +114,59 @@ func SSHRun (router_ip, port, username, password, command, argument, suffix stri
}
}
}
return output
}
// get router name from config file
func GetRouterName (RouterId string) string {
var RouterName string
RouterName = viper.GetString(RouterId+".name")
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
func ParseRoutersFromConfig (enabled string) []Routers {
var allkeys []string
var routers []Routers
// get all keys from config
allkeys = viper.AllKeys()
sort.Strings(allkeys)
for i := range allkeys {
func ParseRoutersFromConfig () []Router {
var routers []Router
var enabled string
enabled = `router[\d]*.enabled`
for i := range AllConfigKeys {
// find those, who match routerNN.enabled
matched, _ := regexp.MatchString(enabled, allkeys[i])
matched, _ := regexp.MatchString(enabled, AllConfigKeys[i])
if matched == true {
//check if enabled = "yes"
var strip = regexp.MustCompile(`\.enabled`)
routerid := strip.ReplaceAllString(allkeys[i], "")
routerid := strip.ReplaceAllString(AllConfigKeys[i], "")
if viper.GetString(routerid+".enabled") == "yes" {
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
}
......@@ -160,11 +176,11 @@ func ShowPage (w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles(datapath+"/page_main.gtpl")
// check HTTP method
if r.Method == "POST" {
var action, argument string
var Command, argument, suffix string
var router_ip, port, username, password string
var ping_command, traceroute_command, showroute_command, command, suffix string
var output DataOut
var allok bool = true
var CommandState bool
// get POST data
input_router := r.PostFormValue("router")
......@@ -181,18 +197,13 @@ func ShowPage (w http.ResponseWriter, r *http.Request) {
port = viper.GetString(input_router+".port")
username = viper.GetString(input_router+".user")
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
if CheckCommand(input_action) == false {
// check and get command for selected action
Command, CommandState = GetCommand(input_router, input_action)
if CommandState == false {
output = PrepareError (RouterList, "Bad command", input_action)
allok = false
} else {
action = input_action
}
// check for argument
......@@ -205,12 +216,11 @@ func ShowPage (w http.ResponseWriter, r *http.Request) {
// connect to router and run command
if allok == true {
command = SelectCommand(action, ping_command, traceroute_command, showroute_command)
// check if command need suffix
if viper.IsSet(input_router+"."+action+"_command_suffix") != false {
suffix = " "+viper.GetString(input_router+"."+action+"_command_suffix")
if viper.IsSet(input_router+".command_"+input_action+"_suffix") != false {
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
t.Execute(w, output)
} else {
......@@ -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() {
// set config
flag.StringVar(&datapath, "data", "", "data directory")
......@@ -240,13 +256,18 @@ func main() {
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
RouterList = ParseRoutersFromConfig(`router[\d]*.enabled`)
RouterList = ParseRoutersFromConfig()
// set http server variables
server_address := viper.GetString("server.address")
server_port := viper.GetString("server.port")
http.HandleFunc("/", ShowPage)
http.HandleFunc("/json", ShowJSON)
// run server
fmt.Println("lookis started")
......
<!DOCTYPE html>
<html>
<head>
<title>Looking Glass</title>
......@@ -37,7 +38,7 @@
<tr>
<td>Argument</td>
<td>&nbsp;</td>
<td><input name="argument" type="input" /></td>
<td><input name="argument" type="text" /></td>
</tr>
<tr>
<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