container_discovery/internal/discoverer/discoverer.go

294 lines
7.7 KiB
Go
Raw Normal View History

2018-04-19 11:36:56 +00:00
package discoverer
import (
"sync"
"git.loafle.net/commons/util-go/net/cidr"
2018-04-26 09:00:24 +00:00
"git.loafle.net/overflow/commons-go/core/util"
ocmd "git.loafle.net/overflow/commons-go/model/discovery"
2018-04-19 11:36:56 +00:00
)
type DiscoveryDataType int
const (
DiscoveryDataTypeNone DiscoveryDataType = iota
DiscoveryDataTypeStart
DiscoveryDataTypeStop
DiscoveryDataTypeError
DiscoveryDataTypeZone
DiscoveryDataTypeHost
DiscoveryDataTypePort
DiscoveryDataTypeService
)
type DiscoveryData struct {
Type DiscoveryDataType
Result interface{}
Error error
}
func (dd *DiscoveryData) Release() {
releaseDiscoveryData(dd)
}
var _discoverer Discoverer
func GetDiscoverer() Discoverer {
if nil == _discoverer {
_discoverer = &defaultDiscoverer{}
}
return _discoverer
}
type Discoverer interface {
Retain() chan *DiscoveryData
Release(dataChan chan *DiscoveryData)
2018-06-04 11:56:19 +00:00
Stop()
2018-04-27 16:20:01 +00:00
DiscoverZone(dataChan chan *DiscoveryData, dz *ocmd.DiscoverZone)
DiscoverHost(dataChan chan *DiscoveryData, zone *ocmd.Zone, dh *ocmd.DiscoverHost)
DiscoverPort(dataChan chan *DiscoveryData, host *ocmd.Host, dp *ocmd.DiscoverPort)
DiscoverSerice(dataChan chan *DiscoveryData, port *ocmd.Port, ds *ocmd.DiscoverService)
2018-04-19 11:36:56 +00:00
}
type defaultDiscoverer struct {
dataChanPool chan chan *DiscoveryData
stopChan chan struct{}
}
func (d *defaultDiscoverer) Retain() chan *DiscoveryData {
if nil == d.dataChanPool {
d.dataChanPool = make(chan chan *DiscoveryData, 1)
d.dataChanPool <- make(chan *DiscoveryData, 256)
}
return <-d.dataChanPool
}
func (d *defaultDiscoverer) Release(dataChan chan *DiscoveryData) {
d.dataChanPool <- dataChan
}
2018-06-04 11:56:19 +00:00
func (d *defaultDiscoverer) Stop() {
2018-04-19 11:36:56 +00:00
if nil != d.stopChan {
close(d.stopChan)
d.stopChan = nil
}
}
2018-04-27 16:20:01 +00:00
func (d *defaultDiscoverer) DiscoverZone(dataChan chan *DiscoveryData, dz *ocmd.DiscoverZone) {
2018-04-19 11:36:56 +00:00
var wg sync.WaitGroup
d.stopChan = make(chan struct{})
2018-04-26 09:00:24 +00:00
dataChan <- retainDiscoveryData(DiscoveryDataTypeStart, util.Now(), nil, nil)
2018-04-19 11:36:56 +00:00
wg.Add(1)
go d.innerDiscoverZone(&wg, dataChan, dz)
wg.Wait()
if nil != d.stopChan {
close(d.stopChan)
d.stopChan = nil
}
2018-04-26 09:00:24 +00:00
dataChan <- retainDiscoveryData(DiscoveryDataTypeStop, util.Now(), nil, nil)
2018-04-19 11:36:56 +00:00
}
2018-04-27 16:20:01 +00:00
func (d *defaultDiscoverer) DiscoverHost(dataChan chan *DiscoveryData, zone *ocmd.Zone, dh *ocmd.DiscoverHost) {
2018-04-19 11:36:56 +00:00
var wg sync.WaitGroup
d.stopChan = make(chan struct{})
2018-04-26 09:00:24 +00:00
dataChan <- retainDiscoveryData(DiscoveryDataTypeStart, util.Now(), nil, nil)
2018-04-19 11:36:56 +00:00
wg.Add(1)
go d.innerDiscoverHost(&wg, dataChan, zone, dh)
wg.Wait()
if nil != d.stopChan {
close(d.stopChan)
d.stopChan = nil
}
2018-04-26 09:00:24 +00:00
dataChan <- retainDiscoveryData(DiscoveryDataTypeStop, util.Now(), nil, nil)
2018-04-19 11:36:56 +00:00
}
2018-04-27 16:20:01 +00:00
func (d *defaultDiscoverer) DiscoverPort(dataChan chan *DiscoveryData, host *ocmd.Host, dp *ocmd.DiscoverPort) {
2018-04-19 11:36:56 +00:00
var wg sync.WaitGroup
d.stopChan = make(chan struct{})
2018-04-26 09:00:24 +00:00
dataChan <- retainDiscoveryData(DiscoveryDataTypeStart, util.Now(), nil, nil)
2018-04-19 11:36:56 +00:00
wg.Add(1)
go d.innerDiscoverPort(&wg, dataChan, host, dp)
wg.Wait()
if nil != d.stopChan {
close(d.stopChan)
d.stopChan = nil
}
2018-04-26 09:00:24 +00:00
dataChan <- retainDiscoveryData(DiscoveryDataTypeStop, util.Now(), nil, nil)
2018-04-19 11:36:56 +00:00
}
2018-04-27 16:20:01 +00:00
func (d *defaultDiscoverer) DiscoverSerice(dataChan chan *DiscoveryData, port *ocmd.Port, ds *ocmd.DiscoverService) {
2018-04-19 11:36:56 +00:00
var wg sync.WaitGroup
d.stopChan = make(chan struct{})
2018-04-26 09:00:24 +00:00
dataChan <- retainDiscoveryData(DiscoveryDataTypeStart, util.Now(), nil, nil)
2018-04-19 11:36:56 +00:00
wg.Add(1)
go d.innerDiscoverSerice(&wg, dataChan, port, ds)
wg.Wait()
if nil != d.stopChan {
close(d.stopChan)
d.stopChan = nil
}
2018-04-26 09:00:24 +00:00
dataChan <- retainDiscoveryData(DiscoveryDataTypeStop, util.Now(), nil, nil)
2018-04-19 11:36:56 +00:00
}
2018-04-27 16:20:01 +00:00
func (d *defaultDiscoverer) innerDiscoverZone(wg *sync.WaitGroup, dataChan chan *DiscoveryData, dz *ocmd.DiscoverZone) {
2018-04-19 11:36:56 +00:00
defer func() {
wg.Done()
}()
taskScan(d,
func(resultChan chan interface{}, errChan chan error, doneChan chan struct{}, stopChan chan struct{}) {
scanZone(dz, resultChan, errChan, doneChan, stopChan)
},
func(result interface{}) {
2018-04-26 09:00:24 +00:00
z := result.(*ocmd.Zone)
dataChan <- retainDiscoveryData(DiscoveryDataTypeZone, util.Now(), z, nil)
2018-04-27 16:20:01 +00:00
if nil != dz.DiscoverHost {
2018-04-19 11:36:56 +00:00
cr, _ := cidr.NewCIDRRanger(z.Network)
2018-04-27 16:20:01 +00:00
dh := &ocmd.DiscoverHost{
2018-06-13 10:20:14 +00:00
MetaIPType: z.MetaIPType,
FirstScanRange: cr.First().String(),
LastScanRange: cr.Last().String(),
DiscoverPort: dz.DiscoverHost.DiscoverPort,
2018-04-19 11:36:56 +00:00
}
2018-06-13 10:20:14 +00:00
2018-04-19 11:36:56 +00:00
wg.Add(1)
2018-04-19 14:45:39 +00:00
go d.innerDiscoverHost(wg, dataChan, z, dh)
2018-04-19 11:36:56 +00:00
}
},
func(err error) {
2018-04-26 09:00:24 +00:00
dataChan <- retainDiscoveryData(DiscoveryDataTypeError, util.Now(), nil, err)
2018-04-19 11:36:56 +00:00
},
)
}
2018-04-27 16:20:01 +00:00
func (d *defaultDiscoverer) innerDiscoverHost(wg *sync.WaitGroup, dataChan chan *DiscoveryData, zone *ocmd.Zone, dh *ocmd.DiscoverHost) {
2018-04-19 11:36:56 +00:00
defer func() {
wg.Done()
}()
taskScan(d,
func(resultChan chan interface{}, errChan chan error, doneChan chan struct{}, stopChan chan struct{}) {
scanHost(zone, dh, resultChan, errChan, doneChan, stopChan)
},
func(result interface{}) {
2018-04-26 09:00:24 +00:00
h := result.(*ocmd.Host)
dataChan <- retainDiscoveryData(DiscoveryDataTypeHost, util.Now(), h, nil)
2018-04-27 16:20:01 +00:00
if nil != dh.DiscoverPort {
2018-04-19 11:36:56 +00:00
wg.Add(1)
2018-04-27 16:20:01 +00:00
go d.innerDiscoverPort(wg, dataChan, h, dh.DiscoverPort)
2018-04-19 11:36:56 +00:00
}
},
func(err error) {
2018-04-26 09:00:24 +00:00
dataChan <- retainDiscoveryData(DiscoveryDataTypeError, util.Now(), nil, err)
2018-04-19 11:36:56 +00:00
},
)
}
2018-04-27 16:20:01 +00:00
func (d *defaultDiscoverer) innerDiscoverPort(wg *sync.WaitGroup, dataChan chan *DiscoveryData, host *ocmd.Host, dp *ocmd.DiscoverPort) {
2018-04-19 11:36:56 +00:00
defer func() {
wg.Done()
}()
taskScan(d,
func(resultChan chan interface{}, errChan chan error, doneChan chan struct{}, stopChan chan struct{}) {
scanPort(host, dp, resultChan, errChan, doneChan, stopChan)
},
func(result interface{}) {
2018-04-26 09:00:24 +00:00
p := result.(*ocmd.Port)
dataChan <- retainDiscoveryData(DiscoveryDataTypePort, util.Now(), p, nil)
2018-04-27 16:20:01 +00:00
if nil != dp.DiscoverService {
2018-04-19 11:36:56 +00:00
wg.Add(1)
2018-04-27 16:20:01 +00:00
go d.innerDiscoverSerice(wg, dataChan, p, dp.DiscoverService)
2018-04-19 11:36:56 +00:00
}
},
func(err error) {
2018-04-26 09:00:24 +00:00
dataChan <- retainDiscoveryData(DiscoveryDataTypeError, util.Now(), nil, err)
2018-04-19 11:36:56 +00:00
},
)
}
2018-04-27 16:20:01 +00:00
func (d *defaultDiscoverer) innerDiscoverSerice(wg *sync.WaitGroup, dataChan chan *DiscoveryData, port *ocmd.Port, ds *ocmd.DiscoverService) {
2018-04-19 11:36:56 +00:00
defer func() {
wg.Done()
}()
taskScan(d,
func(resultChan chan interface{}, errChan chan error, doneChan chan struct{}, stopChan chan struct{}) {
scanService(port, ds, resultChan, errChan, doneChan, stopChan)
},
func(result interface{}) {
2018-04-26 09:00:24 +00:00
s := result.(*ocmd.Service)
dataChan <- retainDiscoveryData(DiscoveryDataTypeService, util.Now(), s, nil)
2018-04-19 11:36:56 +00:00
},
func(err error) {
2018-04-26 09:00:24 +00:00
dataChan <- retainDiscoveryData(DiscoveryDataTypeError, util.Now(), nil, err)
2018-04-19 11:36:56 +00:00
},
)
}
func taskScan(d *defaultDiscoverer,
taskFunc func(resultChan chan interface{}, errChan chan error, doneChan chan struct{}, stopChan chan struct{}),
reesultFunc func(result interface{}),
errorFunc func(err error)) {
resultChan := make(chan interface{})
errChan := make(chan error)
stopChan := make(chan struct{})
doneChan := make(chan struct{})
defer func() {
}()
go taskFunc(resultChan, errChan, doneChan, stopChan)
for {
select {
case r := <-resultChan:
reesultFunc(r)
case err := <-errChan:
errorFunc(err)
case <-doneChan:
return
case <-d.stopChan:
close(stopChan)
<-doneChan
return
}
}
}
var discoveryDataPool sync.Pool
2018-04-26 09:00:24 +00:00
func retainDiscoveryData(discoveryDataType DiscoveryDataType, t util.Timestamp, result interface{}, err error) *DiscoveryData {
2018-04-19 11:36:56 +00:00
v := discoveryDataPool.Get()
var discoveryData *DiscoveryData
if v == nil {
discoveryData = &DiscoveryData{}
} else {
discoveryData = v.(*DiscoveryData)
}
discoveryData.Type = discoveryDataType
discoveryData.Result = result
discoveryData.Error = err
return discoveryData
}
func releaseDiscoveryData(discoveryData *DiscoveryData) {
discoveryData.Type = DiscoveryDataTypeNone
discoveryData.Result = nil
discoveryData.Error = nil
discoveryDataPool.Put(discoveryData)
}