func (p *Params) Login() (connection interface{}, loginInfo LoginInfo, err error) {
	if os.Getenv("DEBUG_BMCLOGIN") == "1" {
		debug = true
	}
	if p.Retries == 0 {
		p.Retries = 1
	}
	p.doneChan = make(chan struct{})
	if p.StopChan != nil {
		go func() {
			select {
			case <-p.StopChan:
				interrupt = true
			case <-p.doneChan:
				return
			}
		}()
	}
	defer close(p.doneChan)
	for _, credentials := range p.Credentials {
		for user, pass := range credentials {
			for _, ip := range p.IpAddresses {
				if ip == "" {
					continue
				}
				for t := 0; t <= p.Retries; t++ {
					if interrupt {
						return connection, loginInfo, errInterrupted
					}
					time.Sleep(time.Duration(backoff) * time.Second)
					loginInfo.Attempts += 1
					connection, ipInactive, err := p.attemptLogin(ip, user, pass)
					if debug {
						log.Printf("DEBUG_BMCLOGIN: Login attempt. IP: %s, User: %s, Pass: %s, Attempt: %d, Err: %s",
							ip, user, pass, loginInfo.Attempts, err)
					}
					if err == errUnrecognizedDevice {
						return connection, loginInfo, err
					}
					if ipInactive {
						if len(p.IpAddresses) == 1 {
							loginInfo.WorkingCredentials = map[string]string{user: pass}
							return connection, loginInfo, err
						}
						break
					}
					if err == nil {
						if debug {
							log.Printf("DEBUG_BMCLOGIN: Login success. IP: %s, User: %s, Pass: %s, Attempt: %d, Err: %s",
								ip, user, pass, loginInfo.Attempts, err)
						}
						loginInfo.ActiveIpAddress = ip
						loginInfo.WorkingCredentials = map[string]string{user: pass}
						return connection, loginInfo, err
					}
					loginInfo.FailedCredentials = append(loginInfo.FailedCredentials, map[string]string{user: pass})
					backoff = loginInfo.Attempts * 10
					if debug {
						log.Printf("DEBUG_BMCLOGIN: Login failed. Backoff: %dsecs IP: %s, User: %s, Pass: %s, Attempt: %d, Err: %s", backoff, ip, user, pass, loginInfo.Attempts, err)
					}
				}
			}
		}
	}
	return connection, loginInfo, errors.New("All attempts to login failed.")
}
Login() carries out login actions.
nolint: gocyclo
package bmclogin
import (
	"errors"
	"fmt"
	"log"
	"os"
	"time"
	"github.com/bmc-toolbox/bmclib/devices"
	"github.com/bmc-toolbox/bmclib/discover"
)
var (
	debug                 bool
	backoff               int
	interrupt             bool
	errUnrecognizedDevice = errors.New("Unrecognized device")
	errInterrupted        = errors.New("Received interrupt during connection setup")
)
type Params struct {
	IpAddresses     []string             
	Credentials     []map[string]string  
	CheckCredential bool                 
	Retries         int                  
	StopChan        <-chan struct{}      
	doneChan        chan struct{}        
}
type LoginInfo struct {
	FailedCredentials  []map[string]string  
	WorkingCredentials map[string]string    
	ActiveIpAddress    string               
	Attempts           int                  
}