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 (
"golang.org/x/crypto/ssh"
)
func page01 (w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("page01.gtpl")
t.Execute(w, nil)
// declare variables for page template
type DataOut struct {
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)
stringoutput := string(byteinput[:byteslen])
return stringoutput
}
func doit (w http.ResponseWriter, r *http.Request) {
type data struct {
Command string
Items string
// 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
}
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")
if net.ParseIP(router) == nil {
log.Fatal("Bad router id: ", router)
t, _ := template.ParseFiles("badinput.gtpl")
t.Execute(w, nil)
} else {
action := r.PostFormValue("action")
argument := r.PostFormValue("argument")
port := viper.GetString(router_id+".port")
username := viper.GetString(router_id+".user")
password := viper.GetString(router_id+".password")
ping_command := viper.GetString(router_id+".ping_command")
traceroute_command := viper.GetString(router_id+".traceroute_command")
showroute_command := viper.GetString(router_id+".showroute_command")
sshConfig := &ssh.ClientConfig {
User: username,
Auth: []ssh.AuthMethod {
}
// 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 = ""
}
return command
}
// connect to router and run command
func SSHRun (router_ip, port, username, password, command, argument string) DataOut {
var rawoutput []byte
var output DataOut
var allok bool = true
// setting auth options
sshConfig := &ssh.ClientConfig {
User: username,
Auth: []ssh.AuthMethod {
ssh.Password(password),
},
}
},
}
connection, err := ssh.Dial("tcp", router+":"+port, sshConfig)
if err != nil {
log.Fatal("unable to connect: ", err)
}
defer connection.Close()
// setting terminal
modes := ssh.TerminalModes {
ssh.ECHO: 0, // disable echoing
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
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()
if err != nil {
log.Fatal("Failed to create session: ", err)
}
modes := ssh.TerminalModes {
ssh.ECHO: 0, // disable echoing
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
session.Close()
log.Fatal("request for pseudo terminal failed: ", err)
output = PrepareError ("Connection failed", "failed to create session")
allok = false
connection.Close()
} else {
// run terminal
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
session.Close()
output = PrepareError ("Connection failed", "Request for pseudo terminal failed")
allok = false
}
}
var rawoutput []byte
if action == "ping" {
rawoutput, err = session.Output(ping_command+" "+argument)
if allok == true {
// run command and save output
rawoutput, err = session.Output(command+" "+argument)
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)
if err != nil {
log.Fatal("Cannot execute command: ", err)
}
}
return output
}
// 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)
if err != nil {
log.Fatal("Cannot execute command: ", err)
}
// check for selected action
if CheckCommand(input_action) == false {
output = PrepareError ("Bad command", input_action)
allok = false
} else {
action = input_action
}
output := data{Command: action, Items: bytetostring(rawoutput)}
t, _ := template.ParseFiles("page02.gtpl")
t.Execute(w, output)
// check for argument
if net.ParseIP(input_argument) == nil {
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 {
t, _ := template.ParseFiles("badinput.gtpl")
// show page without result
t.Execute(w, nil)
}
}
func main() {
// set config
viper.SetConfigName("config")
viper.SetConfigType("toml")
viper.AddConfigPath(".")
......@@ -114,12 +199,13 @@ func main() {
panic(fmt.Errorf("Fatal error config file: %s \n", errconfig))
}
// set http server variables
server_address := viper.GetString("server.address")
server_port := viper.GetString("server.port")
http.HandleFunc("/", page01)
http.HandleFunc("/do", doit)
http.HandleFunc("/", ShowPage)
fmt.Println("started")
// run server
fmt.Println("lookis started")
errserver := http.ListenAndServe(server_address+":"+server_port, nil)
if errserver != nil {
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 @@
</head>
<body>
<p>&nbsp;</p>
<form action="/do" method="post">
<form action="/" method="post">
<table style="margin-left: auto; margin-right: auto;">
<tbody>
<tr>
......@@ -49,5 +49,15 @@
</tbody>
</table>
</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>
</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