// Files will list all of the file and directory information in the given <path>. func (j *Junos) Files(path string) (*FileList, error) { dir := strings.TrimRight(path, "/") var files FileList var command = fmt.Sprintf(rpcFileList, dir+"/") errMessage := "No output available. Please check the syntax of your command." reply, err := j.Session.Exec(netconf.RawRPC(command)) if err != nil { return nil, err } if reply.Errors != nil { for _, m := range reply.Errors { return nil, errors.New(m.Message) } } if reply.Data == "" { return nil, errors.New(errMessage) } data := strings.Replace(reply.Data, "\n", "", -1) err = xml.Unmarshal([]byte(data), &files) if err != nil { return nil, err } if len(files.Error) > 0 { return nil, fmt.Errorf("%s: No such file or directory", path) } return &files, nil }
// CommitFull does a full commit on the configuration, which requires all daemons to // check and evaluate the new configuration. Useful for when you get an error with // a commit or when you've changed the configuration significantly. func (j *Junos) CommitFull() error { var errs commitResults reply, err := j.Session.Exec(netconf.RawRPC(rpcCommitFull)) if err != nil { return err } if reply.Errors != nil { for _, m := range reply.Errors { return errors.New(m.Message) } } err = xml.Unmarshal([]byte(reply.Data), &errs) if err != nil { return err } if errs.Errors != nil { for _, m := range errs.Errors { message := fmt.Sprintf("[%s]\n %s\nError: %s", strings.Trim(m.Path, "[\r\n]"), strings.Trim(m.Element, "[\r\n]"), strings.Trim(m.Message, "[\r\n]")) return errors.New(message) } } return nil }
// RollbackConfig loads and commits the configuration of a given rollback or rescue state. func (j *Junos) RollbackConfig(option interface{}) error { var command = fmt.Sprintf(rpcRollbackConfig, option) if option == "rescue" { command = fmt.Sprintf(rpcRescueConfig) } reply, err := j.Session.Exec(netconf.RawRPC(command)) if err != nil { return err } err = j.Commit() if err != nil { return err } if reply.Errors != nil { for _, m := range reply.Errors { return errors.New(m.Message) } } return nil }
// Reboot will reboot the device. func (j *Junos) Reboot() error { reply, err := j.Session.Exec(netconf.RawRPC(rpcReboot)) if err != nil { return err } if reply.Errors != nil { for _, m := range reply.Errors { return errors.New(m.Message) } } return nil }
// GetConfig returns the full configuration, or configuration starting at <section>. // <format> can be one of "text" or "xml." You can do sub-sections by separating the // <section> path with a ">" symbol, i.e. "system>login" or "protocols>ospf>area". func (j *Junos) GetConfig(section, format string) (string, error) { secs := strings.Split(section, ">") nSecs := len(secs) - 1 command := fmt.Sprintf("<get-configuration format=\"%s\"><configuration>", format) if section == "full" { command += "</configuration></get-configuration>" } if nSecs >= 0 { for i := 0; i < nSecs; i++ { command += fmt.Sprintf("<%s>", secs[i]) } command += fmt.Sprintf("<%s/>", secs[nSecs]) for j := nSecs - 1; j >= 0; j-- { command += fmt.Sprintf("</%s>", secs[j]) } command += fmt.Sprint("</configuration></get-configuration>") } reply, err := j.Session.Exec(netconf.RawRPC(command)) if err != nil { return "", err } if reply.Errors != nil { for _, m := range reply.Errors { return "", errors.New(m.Message) } } if format == "text" { var output commandXML err = xml.Unmarshal([]byte(reply.Data), &output) if err != nil { return "", err } return output.Config, nil } return reply.Data, nil }
// Rescue will create or delete the rescue configuration given "save" or "delete." func (j *Junos) Rescue(action string) error { command := fmt.Sprintf(rpcRescueSave) if action == "delete" { command = fmt.Sprintf(rpcRescueDelete) } reply, err := j.Session.Exec(netconf.RawRPC(command)) if err != nil { return err } if reply.Errors != nil { for _, m := range reply.Errors { return errors.New(m.Message) } } return nil }
// ConfigDiff compares the current active configuration to a given rollback configuration. func (j *Junos) ConfigDiff(compare int) (string, error) { var rb diffXML command := fmt.Sprintf(rpcGetRollbackCompare, compare) reply, err := j.Session.Exec(netconf.RawRPC(command)) if err != nil { return "", err } if reply.Errors != nil { for _, m := range reply.Errors { return "", errors.New(m.Message) } } err = xml.Unmarshal([]byte(reply.Data), &rb) if err != nil { return "", err } return rb.Config, nil }
// CommitHistory gathers all the information about previous commits. func (j *Junos) CommitHistory() (*CommitHistory, error) { var history CommitHistory reply, err := j.Session.Exec(netconf.RawRPC(rpcCommitHistory)) if err != nil { return nil, err } if reply.Errors != nil { for _, m := range reply.Errors { return nil, errors.New(m.Message) } } if reply.Data == "" { return nil, errors.New("could not load commit history") } err = xml.Unmarshal([]byte(reply.Data), &history) if err != nil { return nil, err } return &history, nil }
// RunCommand executes any operational mode command, such as "show" or "request." // <format> can be one of "text" or "xml." func (j *Junos) RunCommand(cmd, format string) (string, error) { var command string command = fmt.Sprintf(rpcCommand, cmd) errMessage := "No output available. Please check the syntax of your command." if format == "xml" { command = fmt.Sprintf(rpcCommandXML, cmd) } reply, err := j.Session.Exec(netconf.RawRPC(command)) if err != nil { return errMessage, err } if reply.Errors != nil { for _, m := range reply.Errors { return errMessage, errors.New(m.Message) } } if reply.Data == "" { return errMessage, nil } if format == "text" { var output commandXML err = xml.Unmarshal([]byte(reply.Data), &output) if err != nil { return "", err } return output.Config, nil } return reply.Data, nil }
// NewSession establishes a new connection to a Junos device that we will use // to run our commands against. NewSession also gathers software information // about the device. func NewSession(host, user, password string) (*Junos, error) { rex := regexp.MustCompile(`^.*\[(.*)\]`) s, err := netconf.DialSSH(host, netconf.SSHConfigPassword(user, password)) if err != nil { log.Fatal(err) } reply, err := s.Exec(netconf.RawRPC(rpcVersion)) if err != nil { return nil, err } if reply.Errors != nil { for _, m := range reply.Errors { return nil, errors.New(m.Message) } } if strings.Contains(reply.Data, "multi-routing-engine-results") { var facts versionRouteEngines err = xml.Unmarshal([]byte(reply.Data), &facts) if err != nil { return nil, err } numRE := len(facts.RE) hostname := facts.RE[0].Hostname res := make([]RoutingEngine, 0, numRE) for i := 0; i < numRE; i++ { version := rex.FindStringSubmatch(facts.RE[i].PackageInfo[0].SoftwareVersion[0]) model := strings.ToUpper(facts.RE[i].Platform) res = append(res, RoutingEngine{Model: model, Version: version[1]}) } return &Junos{ Session: s, Hostname: hostname, RoutingEngines: numRE, Platform: res, }, nil } var facts versionRouteEngine err = xml.Unmarshal([]byte(reply.Data), &facts) if err != nil { return nil, err } // res := make([]RoutingEngine, 0) var res []RoutingEngine hostname := facts.Hostname version := rex.FindStringSubmatch(facts.PackageInfo[0].SoftwareVersion[0]) model := strings.ToUpper(facts.Platform) res = append(res, RoutingEngine{Model: model, Version: version[1]}) return &Junos{ Session: s, Hostname: hostname, RoutingEngines: 1, Platform: res, }, nil }
// Config loads a given configuration file from your local machine, // a remote (FTP or HTTP server) location, or via configuration statements // from variables (type string or []string) within your script. Format can be one of // "set" "text" or "xml." func (j *Junos) Config(path interface{}, format string, commit bool) error { var command string switch format { case "set": switch path.(type) { case string: if strings.Contains(path.(string), "tp://") { command = fmt.Sprintf(rpcConfigURLSet, path.(string)) } if _, err := ioutil.ReadFile(path.(string)); err != nil { command = fmt.Sprintf(rpcConfigStringSet, path.(string)) } else { data, err := ioutil.ReadFile(path.(string)) if err != nil { return err } command = fmt.Sprintf(rpcConfigFileSet, string(data)) } case []string: command = fmt.Sprintf(rpcConfigStringSet, strings.Join(path.([]string), "\n")) } case "text": switch path.(type) { case string: if strings.Contains(path.(string), "tp://") { command = fmt.Sprintf(rpcConfigURLText, path.(string)) } if _, err := ioutil.ReadFile(path.(string)); err != nil { command = fmt.Sprintf(rpcConfigStringText, path.(string)) } else { data, err := ioutil.ReadFile(path.(string)) if err != nil { return err } command = fmt.Sprintf(rpcConfigFileText, string(data)) } case []string: command = fmt.Sprintf(rpcConfigStringText, strings.Join(path.([]string), "\n")) } case "xml": switch path.(type) { case string: if strings.Contains(path.(string), "tp://") { command = fmt.Sprintf(rpcConfigURLXML, path.(string)) } if _, err := ioutil.ReadFile(path.(string)); err != nil { command = fmt.Sprintf(rpcConfigStringXML, path.(string)) } else { data, err := ioutil.ReadFile(path.(string)) if err != nil { return err } command = fmt.Sprintf(rpcConfigFileXML, string(data)) } case []string: command = fmt.Sprintf(rpcConfigStringXML, strings.Join(path.([]string), "\n")) } } reply, err := j.Session.Exec(netconf.RawRPC(command)) if err != nil { return err } if commit { err = j.Commit() if err != nil { return err } } if reply.Errors != nil { for _, m := range reply.Errors { return errors.New(m.Message) } } return nil }