diff --git a/conf/conf.go b/conf/conf.go index ccca193..8765a95 100644 --- a/conf/conf.go +++ b/conf/conf.go @@ -40,6 +40,14 @@ func (a *AppConfig) Dump() ([]byte, error) { return b, nil } +func NewDevAttr() DevAttributes { + a := DevAttributes{ + ErrlogHistSize: 60, // default max number of lines in errlog history + } + + return a +} + type DevAttributes struct { NeedLoginChat bool // need login chat NeedEnabledMode bool // need enabled mode @@ -60,6 +68,7 @@ type DevAttributes struct { S3ContentType string // ""=none "detect"=http.Detect "text/plain" etc RunProg []string // "/path/to/external/command", "arg1", "arg2" for the run model RunTimeout time.Duration // 60s - time allowed for external program to complete + ErrlogHistSize int // max number of lines in errlog history // readTimeout: per-read timeout (protection against inactivity) // matchTimeout: full match timeout (protection against slow sender -- think 1 byte per second) diff --git a/dev/model_cisco.go b/dev/model_cisco.go index 2f85a5c..89d41ad 100644 --- a/dev/model_cisco.go +++ b/dev/model_cisco.go @@ -7,29 +7,28 @@ import ( ) func registerModelCiscoIOS(logger hasPrintf, t *DeviceTable) { - modelName := "cisco-ios" - m := &Model{name: modelName} + a := conf.NewDevAttr() - m.defaultAttr = conf.DevAttributes{ - NeedLoginChat: true, - NeedEnabledMode: true, - NeedPagingOff: true, - EnableCommand: "enable", - UsernamePromptPattern: `Username:\s*$`, - PasswordPromptPattern: `Password:\s*$`, - EnablePasswordPromptPattern: `Password:\s*$`, - DisabledPromptPattern: `\S+>\s*$`, - EnabledPromptPattern: `\S+#\s*$`, - CommandList: []string{"show ver", "show run"}, - DisablePagerCommand: "term len 0", - ReadTimeout: 10 * time.Second, - MatchTimeout: 20 * time.Second, - SendTimeout: 5 * time.Second, - CommandReadTimeout: 20 * time.Second, // larger timeout for slow 'sh run' - CommandMatchTimeout: 30 * time.Second, // larger timeout for slow 'sh run' - QuoteSentCommandsFormat: `!![%s]`, - } + a.NeedLoginChat = true + a.NeedEnabledMode = true + a.NeedPagingOff = true + a.EnableCommand = "enable" + a.UsernamePromptPattern = `Username:\s*$` + a.PasswordPromptPattern = `Password:\s*$` + a.EnablePasswordPromptPattern = `Password:\s*$` + a.DisabledPromptPattern = `\S+>\s*$` + a.EnabledPromptPattern = `\S+#\s*$` + a.CommandList = []string{"show ver", "show run"} + a.DisablePagerCommand = "term len 0" + a.ReadTimeout = 10 * time.Second + a.MatchTimeout = 20 * time.Second + a.SendTimeout = 5 * time.Second + a.CommandReadTimeout = 20 * time.Second // larger timeout for slow 'sh run' + a.CommandMatchTimeout = 30 * time.Second // larger timeout for slow 'sh run' + a.QuoteSentCommandsFormat = `!![%s]` + m := &Model{name: "cisco-ios"} + m.defaultAttr = a if err := t.SetModel(m, logger); err != nil { logger.Printf("registerModelCiscoIOS: %v", err) } diff --git a/dev/model_cisco_iosxr.go b/dev/model_cisco_iosxr.go index c213ea7..3e97d3a 100644 --- a/dev/model_cisco_iosxr.go +++ b/dev/model_cisco_iosxr.go @@ -6,30 +6,29 @@ import ( ) func registerModelCiscoIOSXR(logger hasPrintf, t *DeviceTable) { - modelName := "cisco-iosxr" - m := &Model{name: modelName} + a := conf.NewDevAttr() - m.defaultAttr = conf.DevAttributes{ - NeedLoginChat: true, - NeedEnabledMode: true, - NeedPagingOff: true, - EnableCommand: "enable", - UsernamePromptPattern: `Username:\s*$`, - PasswordPromptPattern: `Password:\s*$`, - EnablePasswordPromptPattern: `Password:\s*$`, - DisabledPromptPattern: `\S+>\s*$`, - EnabledPromptPattern: `\S+#\s*$`, - CommandList: []string{"show ver br", "show run"}, - DisablePagerCommand: "term len 0", - ReadTimeout: 10 * time.Second, - MatchTimeout: 20 * time.Second, - SendTimeout: 5 * time.Second, - CommandReadTimeout: 20 * time.Second, // larger timeout for slow 'sh run' - CommandMatchTimeout: 30 * time.Second, // larger timeout for slow 'sh run' - QuoteSentCommandsFormat: `!![%s]`, - LineFilter: "iosxr", // line filter name - applied to every saved line - } + a.NeedLoginChat = true + a.NeedEnabledMode = true + a.NeedPagingOff = true + a.EnableCommand = "enable" + a.UsernamePromptPattern = `Username:\s*$` + a.PasswordPromptPattern = `Password:\s*$` + a.EnablePasswordPromptPattern = `Password:\s*$` + a.DisabledPromptPattern = `\S+>\s*$` + a.EnabledPromptPattern = `\S+#\s*$` + a.CommandList = []string{"show ver br", "show run"} + a.DisablePagerCommand = "term len 0" + a.ReadTimeout = 10 * time.Second + a.MatchTimeout = 20 * time.Second + a.SendTimeout = 5 * time.Second + a.CommandReadTimeout = 20 * time.Second // larger timeout for slow 'sh run' + a.CommandMatchTimeout = 30 * time.Second // larger timeout for slow 'sh run' + a.QuoteSentCommandsFormat = `!![%s]` + a.LineFilter = "iosxr" // line filter name - applied to every saved line + m := &Model{name: "cisco-iosxr"} + m.defaultAttr = a if err := t.SetModel(m, logger); err != nil { logger.Printf("registerModelCiscoIOSXR: %v", err) } diff --git a/dev/model_http.go b/dev/model_http.go index eae906e..8c2b361 100644 --- a/dev/model_http.go +++ b/dev/model_http.go @@ -7,30 +7,19 @@ import ( ) func registerModelHTTP(logger hasPrintf, t *DeviceTable) { - modelName := "http" - m := &Model{name: modelName} + a := conf.NewDevAttr() - m.defaultAttr = conf.DevAttributes{ - NeedLoginChat: false, - NeedEnabledMode: false, - NeedPagingOff: false, - EnableCommand: "", - UsernamePromptPattern: "", - PasswordPromptPattern: "", - EnablePasswordPromptPattern: "", - DisabledPromptPattern: "", - EnabledPromptPattern: "", - CommandList: []string{"GET / HTTP/1.0\r\n\r\n"}, - DisablePagerCommand: "", - ReadTimeout: 5 * time.Second, - MatchTimeout: 10 * time.Second, - SendTimeout: 5 * time.Second, - CommandReadTimeout: 5 * time.Second, // larger timeout for slow 'sh run' - CommandMatchTimeout: 10 * time.Second, // larger timeout for slow 'sh run' - SupressAutoLF: true, - QuoteSentCommandsFormat: `[%s]`, - } + a.CommandList = []string{"GET / HTTP/1.0\r\n\r\n"} + a.ReadTimeout = 5 * time.Second + a.MatchTimeout = 10 * time.Second + a.SendTimeout = 5 * time.Second + a.CommandReadTimeout = 5 * time.Second // larger timeout for slow 'sh run' + a.CommandMatchTimeout = 10 * time.Second // larger timeout for slow 'sh run' + a.SupressAutoLF = true + a.QuoteSentCommandsFormat = `[%s]` + m := &Model{name: "http"} + m.defaultAttr = a if err := t.SetModel(m, logger); err != nil { logger.Printf("registerModelHTTP: %v", err) } diff --git a/dev/model_junos.go b/dev/model_junos.go index 764a3c3..980ea73 100644 --- a/dev/model_junos.go +++ b/dev/model_junos.go @@ -7,30 +7,29 @@ import ( ) func registerModelJunOS(logger hasPrintf, t *DeviceTable) { - modelName := "junos" - m := &Model{name: modelName} + a := conf.NewDevAttr() - m.defaultAttr = conf.DevAttributes{ - NeedLoginChat: true, - NeedEnabledMode: false, - NeedPagingOff: true, - EnableCommand: "", - UsernamePromptPattern: `login:\s*$`, - PasswordPromptPattern: `Password:\s*$`, - EnablePasswordPromptPattern: "", - DisabledPromptPattern: `\S+>\s*$`, - EnabledPromptPattern: `\S+>\s*$`, - CommandList: []string{"show ver", "show conf | disp set"}, - DisablePagerCommand: "set cli screen-length 0", - ReadTimeout: 10 * time.Second, - MatchTimeout: 20 * time.Second, - SendTimeout: 5 * time.Second, - CommandReadTimeout: 20 * time.Second, // larger timeout for slow 'sh run' - CommandMatchTimeout: 30 * time.Second, // larger timeout for slow 'sh run' - QuoteSentCommandsFormat: `##[%s]`, - S3ContentType: "detect", - } + a.NeedLoginChat = true + a.NeedEnabledMode = false + a.NeedPagingOff = true + a.EnableCommand = "" + a.UsernamePromptPattern = `login:\s*$` + a.PasswordPromptPattern = `Password:\s*$` + a.EnablePasswordPromptPattern = "" + a.DisabledPromptPattern = `\S+>\s*$` + a.EnabledPromptPattern = `\S+>\s*$` + a.CommandList = []string{"show ver", "show conf | disp set"} + a.DisablePagerCommand = "set cli screen-length 0" + a.ReadTimeout = 10 * time.Second + a.MatchTimeout = 20 * time.Second + a.SendTimeout = 5 * time.Second + a.CommandReadTimeout = 20 * time.Second // larger timeout for slow 'sh run' + a.CommandMatchTimeout = 30 * time.Second // larger timeout for slow 'sh run' + a.QuoteSentCommandsFormat = `##[%s]` + a.S3ContentType = "detect" + m := &Model{name: "junos"} + m.defaultAttr = a if err := t.SetModel(m, logger); err != nil { logger.Printf("registerModelJunOS: %v", err) } diff --git a/dev/model_linux.go b/dev/model_linux.go index 8254716..2941572 100644 --- a/dev/model_linux.go +++ b/dev/model_linux.go @@ -7,29 +7,28 @@ import ( ) func registerModelLinux(logger hasPrintf, t *DeviceTable) { - modelName := "linux" - m := &Model{name: modelName} + a := conf.NewDevAttr() - m.defaultAttr = conf.DevAttributes{ - NeedLoginChat: true, - NeedEnabledMode: false, - NeedPagingOff: false, - EnableCommand: "", - UsernamePromptPattern: `Username:\s*$`, - PasswordPromptPattern: `Password:\s*$`, - EnablePasswordPromptPattern: "", - DisabledPromptPattern: `\$\s*$`, - EnabledPromptPattern: `\$\s*$`, - CommandList: []string{"", "/bin/uname -a", "/usr/bin/uptime", "/bin/ls"}, // "" = dont send, wait for command prompt - DisablePagerCommand: "", - ReadTimeout: 5 * time.Second, - MatchTimeout: 10 * time.Second, - SendTimeout: 5 * time.Second, - CommandReadTimeout: 10 * time.Second, - CommandMatchTimeout: 10 * time.Second, - QuoteSentCommandsFormat: `##[%s]`, - } + a.NeedLoginChat = true + a.NeedEnabledMode = false + a.NeedPagingOff = false + a.EnableCommand = "" + a.UsernamePromptPattern = `Username:\s*$` + a.PasswordPromptPattern = `Password:\s*$` + a.EnablePasswordPromptPattern = "" + a.DisabledPromptPattern = `\$\s*$` + a.EnabledPromptPattern = `\$\s*$` + a.CommandList = []string{"", "/bin/uname -a", "/usr/bin/uptime", "/bin/ls"} // "" = dont send, wait for command prompt + a.DisablePagerCommand = "" + a.ReadTimeout = 5 * time.Second + a.MatchTimeout = 10 * time.Second + a.SendTimeout = 5 * time.Second + a.CommandReadTimeout = 10 * time.Second + a.CommandMatchTimeout = 10 * time.Second + a.QuoteSentCommandsFormat = `##[%s]` + m := &Model{name: "linux"} + m.defaultAttr = a if err := t.SetModel(m, logger); err != nil { logger.Printf("registerModelLinux: %v", err) } diff --git a/dev/model_run.go b/dev/model_run.go index abf6119..8a2ad6f 100644 --- a/dev/model_run.go +++ b/dev/model_run.go @@ -7,20 +7,20 @@ import ( ) func registerModelRun(logger hasPrintf, t *DeviceTable) { - m := &Model{name: "run"} + a := conf.NewDevAttr() - m.defaultAttr = conf.DevAttributes{ - RunProg: []string{"/bin/bash", "-c", "env | egrep ^JAZIGO_"}, - RunTimeout: 60 * time.Second, - EnabledPromptPattern: "", // "" --> look for EOF - CommandList: []string{""}, // "" = dont send, wait for command prompt - ReadTimeout: 5 * time.Second, - MatchTimeout: 10 * time.Second, - SendTimeout: 5 * time.Second, - CommandReadTimeout: 10 * time.Second, - CommandMatchTimeout: 10 * time.Second, - } + a.RunProg = []string{"/bin/bash", "-c", "env | egrep ^JAZIGO_"} + a.RunTimeout = 60 * time.Second + a.EnabledPromptPattern = "" // "" --> look for EOF + a.CommandList = []string{""} // "" = dont send, wait for command prompt + a.ReadTimeout = 5 * time.Second + a.MatchTimeout = 10 * time.Second + a.SendTimeout = 5 * time.Second + a.CommandReadTimeout = 10 * time.Second + a.CommandMatchTimeout = 10 * time.Second + m := &Model{name: "run"} + m.defaultAttr = a if err := t.SetModel(m, logger); err != nil { logger.Printf("registerModelRun: %v", err) } diff --git a/jazigo/web_ui.go b/jazigo/web_ui.go index dc7d0a5..5f42ce9 100644 --- a/jazigo/web_ui.go +++ b/jazigo/web_ui.go @@ -603,6 +603,8 @@ func buildCreateDevPanel(jaz *app, s gwu.Session, refresh func(gwu.Event), creat textPass := gwu.NewTextBox("") textEnable := gwu.NewTextBox("") + listModel.SetSelected(0, true) + inputCols := 10 textId.SetCols(inputCols) textHost.SetCols(inputCols) @@ -659,7 +661,14 @@ func buildCreateDevPanel(jaz *app, s gwu.Session, refresh func(gwu.Event), creat When: time.Now(), } - if createErr := dev.CreateDevice(jaz.table, jaz.logger, listModel.SelectedValue(), id, textHost.Text(), textTransport.Text(), textUser.Text(), textPass.Text(), textEnable.Text(), false, &change); createErr != nil { + mod := listModel.SelectedValue() + if mod == "" { + msg.SetText(fmt.Sprintf("Invalid model: [%s]", mod)) + e.MarkDirty(createDevPanel) + return + } + + if createErr := dev.CreateDevice(jaz.table, jaz.logger, mod, id, textHost.Text(), textTransport.Text(), textUser.Text(), textPass.Text(), textEnable.Text(), false, &change); createErr != nil { msg.SetText("Could not create device: " + createErr.Error()) e.MarkDirty(createDevPanel) return