func NewRpcClientDriver(rawDriverData []byte, driverName string) (*RpcClientDriver, error) { mcnName := "" p := localbinary.NewLocalBinaryPlugin(driverName) go func() { if err := p.Serve(); err != nil { // If we can't safely load the server, best to just // bail. log.Fatal(err) } }() addr, err := p.Address() if err != nil { return nil, fmt.Errorf("Error attempting to get plugin server address for RPC: %s", err) } rpcclient, err := rpc.DialHTTP("tcp", addr) if err != nil { return nil, err } c := &RpcClientDriver{ Client: NewInternalClient(rpcclient), heartbeatDoneCh: make(chan bool), } go func(heartbeatDoneCh <-chan bool) { for { select { case <-heartbeatDoneCh: return default: if err := c.Client.Call("RpcServerDriver.Heartbeat", struct{}{}, nil); err != nil { log.Warnf("Error attempting heartbeat call to plugin server: %s", err) } time.Sleep(heartbeatInterval) } } }(c.heartbeatDoneCh) var version int if err := c.Client.Call("RpcServerDriver.GetVersion", struct{}{}, &version); err != nil { return nil, err } log.Debug("Using API Version ", version) if err := c.SetConfigRaw(rawDriverData); err != nil { return nil, err } mcnName = c.GetMachineName() p.MachineName = mcnName c.Client.MachineName = mcnName c.plugin = p return c, nil }
func NewRpcClientDriver(rawDriverData []byte, driverName string) (*RpcClientDriver, error) { mcnName := "" p := localbinary.NewLocalBinaryPlugin(driverName) c := &RpcClientDriver{} go func() { if err := p.Serve(); err != nil { // If we can't safely load the server, best to just // bail. log.Fatal(err) } }() addr, err := p.Address() if err != nil { return nil, fmt.Errorf("Error attempting to get plugin server address for RPC: %s", err) } rpcclient, err := rpc.DialHTTP("tcp", addr) if err != nil { return nil, err } c.Client = NewInternalClient(rpcclient) go func() { for { call := <-c.Client.Calls log.Debugf("(%s) Got msg %+v", mcnName, call) if call.ServiceMethod == "RpcServerDriver.Close" { p.Close() } c.Client.CallErrs <- c.Client.RpcClient.Call(call.ServiceMethod, call.Args, call.Reply) if call.ServiceMethod == "RpcServerDriver.Close" { // If we're messaging the server to close, // we're not accepting any more RPC calls at // all, so return from this function // (subsequent "requests" to make a call by // sending on the Calls channel will simply // block and never go through) return } } }() var version int if err := c.Client.Call("RpcServerDriver.GetVersion", struct{}{}, &version); err != nil { return nil, err } log.Debug("Using API Version ", version) if err := c.SetConfigRaw(rawDriverData); err != nil { return nil, err } mcnName = c.GetMachineName() p.MachineName = mcnName return c, nil }
func NewRpcClientDriver(rawDriverData []byte, driverName string) (*RpcClientDriver, error) { mcnName := "" p, err := localbinary.NewLocalBinaryPlugin(driverName) if err != nil { return nil, err } go func() { if err := p.Serve(); err != nil { // TODO: Is this best approach? log.Warn(err) return } }() addr, err := p.Address() if err != nil { return nil, fmt.Errorf("Error attempting to get plugin server address for RPC: %s", err) } rpcclient, err := rpc.DialHTTP("tcp", addr) if err != nil { return nil, err } c := &RpcClientDriver{ Client: NewInternalClient(rpcclient), heartbeatDoneCh: make(chan bool), } go func(c *RpcClientDriver) { for { select { case <-c.heartbeatDoneCh: return default: if err := c.Client.Call("RpcServerDriver.Heartbeat", struct{}{}, nil); err != nil { log.Warnf("Error attempting heartbeat call to plugin server: %s", err) c.Close() return } time.Sleep(heartbeatInterval) } } }(c) var serverVersion int if err := c.Client.Call("RpcServerDriver.GetVersion", struct{}{}, &serverVersion); err != nil { return nil, err } if serverVersion != version.APIVersion { return nil, fmt.Errorf("Driver binary uses an incompatible API version (%d)", serverVersion) } log.Debug("Using API Version ", serverVersion) if err := c.SetConfigRaw(rawDriverData); err != nil { return nil, err } mcnName = c.GetMachineName() p.MachineName = mcnName c.Client.MachineName = mcnName c.plugin = p return c, nil }