Skip to content
Snippets Groups Projects

Develop

Merged Ghost User requested to merge develop into master
3 files
+ 51
44
Compare changes
  • Side-by-side
  • Inline
Files
3
  • - Removed Goroutine in `createCsbiDevice` and calls of `panic()` have been
      changed to `return err`
    - `createCsbiDevice` is now called as Goroutine from within the
      `handleCsbiEnrolment` method.
    - Error handling is done by using a `ErrorGroup`
    
    These changes prevent that panics are thrown from a Goroutine that was
    originally called from `createCsbiDevice`. Now normal errors are thrown
    and catched with the help of a `ErrorGroup`.
    
    Fixes: #171
@@ -10,6 +10,7 @@ import (
"code.fbi.h-da.de/danet/gosdn/metrics"
"code.fbi.h-da.de/danet/gosdn/nucleus/types"
"golang.org/x/sync/errgroup"
cpb "code.fbi.h-da.de/danet/api/go/gosdn/csbi"
ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd"
@@ -401,6 +402,7 @@ func (pnd *pndImplementation) handleCsbiDeletion(id uuid.UUID) error {
}
func (pnd *pndImplementation) handleCsbiEnrolment(name string, opt *tpb.TransportOption) error {
g := new(errgroup.Group)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5)
defer cancel()
req := &cpb.CreateRequest{
@@ -412,61 +414,65 @@ func (pnd *pndImplementation) handleCsbiEnrolment(name string, opt *tpb.Transpor
return err
}
for _, d := range resp.Deployments {
if err := pnd.createCsbiDevice(ctx, name, d, opt); err != nil {
log.Error(err)
}
dCopy := d
g.Go(func() error {
return pnd.createCsbiDevice(ctx, name, dCopy, opt)
})
}
err = g.Wait()
if err != nil {
return err
}
return nil
}
// createCsbiDevice is a helper method for cSBI device creation. The method
// waits for a SYN (which indicates that the cSBI is running and addressable)
// of the commissioned cSBI and creates the device within the controller.
func (pnd *pndImplementation) createCsbiDevice(ctx context.Context, name string, d *cpb.Deployment, opt *tpb.TransportOption) error {
defer func() {
if r := recover(); r != nil {
log.Errorf("recovered in sbi enrolment: %v", r)
}
}()
id, err := uuid.Parse(d.Id)
if err != nil {
return err
}
ch := make(chan store.DeviceDetails, 1)
pnd.callback(id, ch)
defer pnd.callback(id, nil)
defer close(ch)
tickatus := time.NewTicker(time.Minute * 1)
go func() {
select {
case <-tickatus.C:
log.WithFields(log.Fields{
"id": d.Id,
"err": ctx.Err(),
}).Error("csbi handshake timed out")
case deviceDetails := <-ch:
log.Infof("syn from csbi %v", deviceDetails.ID)
id, err := uuid.Parse(deviceDetails.ID)
if err != nil {
panic(err)
}
csbiTransportOptions := &tpb.TransportOption{
Address: deviceDetails.Address,
Username: opt.Username,
Password: opt.Password,
Tls: opt.Tls,
Type: opt.Type,
TransportOption: opt.TransportOption,
}
log.WithField("transport option", csbiTransportOptions).Debug("gosdn gnmi transport options")
d, err := NewDevice(name, uuid.Nil, csbiTransportOptions, csbi)
if err != nil {
panic(err)
}
d.(*CsbiDevice).UUID = id
ch <- store.DeviceDetails{TransportOption: opt}
if err := pnd.devices.Add(d, d.Name()); err != nil {
panic(err)
}
defer tickatus.Stop()
select {
case <-tickatus.C:
log.WithFields(log.Fields{
"id": d.Id,
"err": ctx.Err(),
}).Error("csbi handshake timed out")
case deviceDetails := <-ch:
log.Infof("syn from csbi %v", deviceDetails.ID)
id, err := uuid.Parse(deviceDetails.ID)
if err != nil {
return err
}
csbiTransportOptions := &tpb.TransportOption{
Address: deviceDetails.Address,
Username: opt.Username,
Password: opt.Password,
Tls: opt.Tls,
Type: opt.Type,
TransportOption: opt.TransportOption,
}
log.WithField("transport option", csbiTransportOptions).Debug("gosdn gnmi transport options")
d, err := NewDevice(name, uuid.Nil, csbiTransportOptions, csbi)
if err != nil {
return err
}
d.(*CsbiDevice).UUID = id
ch <- store.DeviceDetails{TransportOption: opt}
if err := pnd.devices.Add(d, d.Name()); err != nil {
return err
}
pnd.callback(id, nil)
close(ch)
}()
}
return nil
}
Loading