Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle connections #3

Open
dbarrosop opened this issue Jun 3, 2019 · 5 comments
Open

handle connections #3

dbarrosop opened this issue Jun 3, 2019 · 5 comments

Comments

@dbarrosop
Copy link
Contributor

Right now connections are handled by tasks, we should have gornir do that in a similar fashion to nornir

@nleiva
Copy link
Collaborator

nleiva commented Jun 3, 2019

Not sure how you do it in nornir, but I think you'd have to re-work how you iterate over the hosts.

func (r ParallelRunner) Run(ctx gornir.Context, task gornir.Task, results chan *gornir.JobResult) error {
...
	for hostname, host := range gr.Inventory.Hosts {
		logger.WithField("host", hostname).Debug("calling function")
		go task.Run(ctx.ForHost(host), r.wg, results)
	}
...
}

For a function that is run in the background, that first connects and then executes the task. Something along the lines of https://github.com/nleiva/xrgrpc/blob/master/example/setconfiglist/main.go#L47-L68. I can help you with this, just need to learn how nornir does it and whether is the best fit for Go.

@dbarrosop
Copy link
Contributor Author

Nornir is a bit more complex/sophisticated for two reasons:

  1. A host can support multiple types of connections; over ssh, http, etc..
  2. A connection may survive multiple calls to Run

I will mock open a draft PR for discussion as I think that will be easier but the idea is to:

  1. Create plugin interface for connections. Something like:
type Connection interface:
   Open(*Host) error
   Close(*Host) error
  1. Then you implement an SSH plugin.
  2. The Host struct now should be extended to:
    a. store established connections
    b. retrieve already established connections or open them otherwise
    c. be able to clean the connections.

From an interface perspective things could look like this:

// main
gr := &Gornir{...}
defer gr.Close() // this will iterate over all the hosts and close the connections
...
// a task
func (t *SomeTaskOverSSH) Run(...) {
    // this either gets an opened connection or establishes a new one
    c, err := host.GetConnection("ssh") 
    if err != nil {
          // handle error or return it
    }
    session = c.(*ssh.Session)
    ...
}

Basically the task doesn't need to bother about opening/closing the connection, gornir handles that instead and if you run multiple tasks that require the same type of connection you don't need to keep opening/closing them.

@nleiva
Copy link
Collaborator

nleiva commented Jun 4, 2019

I was thinking about this. Forgot to open a new issues, but I think it would be better we operate over a Device interface, which defines the behavior of any given host. Something like:

type Device interface {
	Connect() err
	SendCommand(s string) err
        ...
}

Then we'd have implementations of this interface for an SSH host, CertSSH host, Netconf host, etc. So the functionality is decoupled from the specifics of the host (transport, authentication, etc.). So I think we are on the same page.

@Ali-aqrabawi
Copy link

if no one is working on this, i would like to start from here, i will try to come up with something and submit a pr to discuss.

@Ali-aqrabawi
Copy link

just submitted #35 for this issue, (yeah i was struggling with fixing the pipeline),

gornir should be able to execute multiple commands in a single connection now by using gomiko,
i didn't attach it to task yet, let me know what do you think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants