Commit 2590a360 authored by zdc's avatar zdc

error handling, functions, structure

* added error handling for bad input and connection problems
* split code to more functions
* change structure and html template - now all information show in one page
parent 80fd6e64
<html>
<head>
<title>Looking Glass</title>
</head>
<body>
<p><strong>Bad input!</strong></p>
<pre></pre>
</body>
</html>
\ No newline at end of file
...@@ -10,102 +10,187 @@ import ( ...@@ -10,102 +10,187 @@ import (
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
) )
func page01 (w http.ResponseWriter, r *http.Request) { // declare variables for page template
t, _ := template.ParseFiles("page01.gtpl") type DataOut struct {
t.Execute(w, nil) OutputHeader, OutputBody string
} }
func bytetostring (byteinput []byte) string { // fill error details
func PrepareError (HeaderRaw, BodyRaw string) DataOut {
log.Print("\nError: ", HeaderRaw, "\nDetails: ", BodyRaw)
output := DataOut{ OutputHeader: HeaderRaw, OutputBody: BodyRaw }
return output
}
// fill normal output
func PrepareOutput (HeaderRaw, BodyRaw string) DataOut {
output := DataOut{ OutputHeader: HeaderRaw, OutputBody: BodyRaw }
return output
}
// convert []byte slice to string
func ByteToString (byteinput []byte) string {
byteslen := len(byteinput) byteslen := len(byteinput)
stringoutput := string(byteinput[:byteslen]) stringoutput := string(byteinput[:byteslen])
return stringoutput return stringoutput
} }
func doit (w http.ResponseWriter, r *http.Request) { // check for correct action
type data struct { func CheckCommand (command string) bool {
Command string switch command {
Items string case "ping":
return true
case "traceroute":
return true
case "showroute":
return true
default:
return false
} }
if net.ParseIP(r.PostFormValue("argument")) != nil && ( r.PostFormValue("action") == "ping" || r.PostFormValue("action") == "traceroute" || r.PostFormValue("action") == "showroute") { }
router_id := r.PostFormValue("router")
router := viper.GetString(router_id+".address") // select command from list
if net.ParseIP(router) == nil { func SelectCommand (command, ping_command, traceroute_command, showroute_command string) string {
log.Fatal("Bad router id: ", router) switch command {
t, _ := template.ParseFiles("badinput.gtpl") case "ping":
t.Execute(w, nil) command = ping_command
} else { case "traceroute":
action := r.PostFormValue("action") command = traceroute_command
argument := r.PostFormValue("argument") case "showroute":
command = showroute_command
port := viper.GetString(router_id+".port") default:
username := viper.GetString(router_id+".user") command = ""
password := viper.GetString(router_id+".password") }
return command
ping_command := viper.GetString(router_id+".ping_command") }
traceroute_command := viper.GetString(router_id+".traceroute_command")
showroute_command := viper.GetString(router_id+".showroute_command") // connect to router and run command
func SSHRun (router_ip, port, username, password, command, argument string) DataOut {
sshConfig := &ssh.ClientConfig { var rawoutput []byte
User: username, var output DataOut
Auth: []ssh.AuthMethod { var allok bool = true
// setting auth options
sshConfig := &ssh.ClientConfig {
User: username,
Auth: []ssh.AuthMethod {
ssh.Password(password), ssh.Password(password),
}, },
} }
connection, err := ssh.Dial("tcp", router+":"+port, sshConfig) // setting terminal
if err != nil { modes := ssh.TerminalModes {
log.Fatal("unable to connect: ", err) ssh.ECHO: 0, // disable echoing
} ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
defer connection.Close() ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
// connect to router
connection, err := ssh.Dial("tcp", router_ip+":"+port, sshConfig)
if err != nil {
output = PrepareError ("Unable to connect", router_ip)
allok = false
}
if allok == true {
// create ssh session
session, err := connection.NewSession() session, err := connection.NewSession()
if err != nil { if err != nil {
log.Fatal("Failed to create session: ", err) output = PrepareError ("Connection failed", "failed to create session")
} allok = false
connection.Close()
modes := ssh.TerminalModes { } else {
ssh.ECHO: 0, // disable echoing // run terminal
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud session.Close()
} output = PrepareError ("Connection failed", "Request for pseudo terminal failed")
allok = false
if err := session.RequestPty("xterm", 80, 40, modes); err != nil { }
session.Close()
log.Fatal("request for pseudo terminal failed: ", err)
} }
var rawoutput []byte if allok == true {
if action == "ping" { // run command and save output
rawoutput, err = session.Output(ping_command+" "+argument) rawoutput, err = session.Output(command+" "+argument)
if err != nil { if err != nil {
log.Fatal("Cannot execute command: ", err) output = PrepareError ("Cannot execute command", command+" "+argument)
allok = false
connection.Close()
} else {
output = PrepareOutput ("Result", ByteToString(rawoutput))
connection.Close()
} }
} }
if action == "traceroute" { }
rawoutput, err = session.Output(traceroute_command+" "+argument) return output
if err != nil { }
log.Fatal("Cannot execute command: ", err)
} // show page and base logic
func ShowPage (w http.ResponseWriter, r *http.Request) {
// select html template
t, _ := template.ParseFiles("page_main.gtpl")
// check HTTP method
if r.Method == "POST" {
var action, argument string
var router_ip, port, username, password string
var ping_command, traceroute_command, showroute_command, command string
var output DataOut
var allok bool = true
// get POST data
input_router := r.PostFormValue("router")
input_action := r.PostFormValue("action")
input_argument := r.PostFormValue("argument")
// check for selected router exist
if viper.IsSet(input_router+".address") == false {
output = PrepareError ("Bad router id", input_router)
allok = false
} else {
// setting router variables from config file
router_ip = viper.GetString(input_router+".address")
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")
} }
if action == "showroute" {
rawoutput, err = session.Output(showroute_command+" "+argument) // check for selected action
if err != nil { if CheckCommand(input_action) == false {
log.Fatal("Cannot execute command: ", err) output = PrepareError ("Bad command", input_action)
} allok = false
} else {
action = input_action
} }
output := data{Command: action, Items: bytetostring(rawoutput)} // check for argument
t, _ := template.ParseFiles("page02.gtpl") if net.ParseIP(input_argument) == nil {
t.Execute(w, output) output = PrepareError ("Bad argument", input_argument)
allok = false
} else {
argument = input_argument
}
// connect to router and run command
if allok == true {
command = SelectCommand(action, ping_command, traceroute_command, showroute_command)
output = SSHRun(router_ip, port, username, password, command, argument)
// show result to user
t.Execute(w, output)
} else {
// show result to user
t.Execute(w, output)
} }
} else { } else {
t, _ := template.ParseFiles("badinput.gtpl") // show page without result
t.Execute(w, nil) t.Execute(w, nil)
} }
} }
func main() { func main() {
// set config
viper.SetConfigName("config") viper.SetConfigName("config")
viper.SetConfigType("toml") viper.SetConfigType("toml")
viper.AddConfigPath(".") viper.AddConfigPath(".")
...@@ -114,12 +199,13 @@ func main() { ...@@ -114,12 +199,13 @@ func main() {
panic(fmt.Errorf("Fatal error config file: %s \n", errconfig)) panic(fmt.Errorf("Fatal error config file: %s \n", errconfig))
} }
// 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("/", page01) http.HandleFunc("/", ShowPage)
http.HandleFunc("/do", doit)
fmt.Println("started") // run server
fmt.Println("lookis started")
errserver := http.ListenAndServe(server_address+":"+server_port, nil) errserver := http.ListenAndServe(server_address+":"+server_port, nil)
if errserver != nil { if errserver != nil {
log.Fatal("ListenAndServe: ", errserver) log.Fatal("ListenAndServe: ", errserver)
......
<html>
<head>
<title>Looking Glass</title>
</head>
<body>
<p><strong>Output for {{.Command}}</strong></p>
<pre>{{.Items}}</pre>
</body>
</html>
\ No newline at end of file
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
</head> </head>
<body> <body>
<p>&nbsp;</p> <p>&nbsp;</p>
<form action="/do" method="post"> <form action="/" method="post">
<table style="margin-left: auto; margin-right: auto;"> <table style="margin-left: auto; margin-right: auto;">
<tbody> <tbody>
<tr> <tr>
...@@ -49,5 +49,15 @@ ...@@ -49,5 +49,15 @@
</tbody> </tbody>
</table> </table>
</form> </form>
<table style="margin-left: auto; margin-right: auto;">
<tbody>
<tr>
<td><strong>{{.OutputHeader}}</strong></td>
</tr>
<tr>
<td><pre>{{.OutputBody}}</pre></td>
</tr>
</tbody>
</table>
</body> </body>
</html> </html>
\ No newline at end of file
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