neighbour.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package neighbour
  2. import (
  3. "encoding/json"
  4. "log"
  5. "time"
  6. "imuslab.com/arozos/mod/cluster/wakeonlan"
  7. "imuslab.com/arozos/mod/database"
  8. "imuslab.com/arozos/mod/network/mdns"
  9. )
  10. /*
  11. This is a module for discovering nearby arozos systems.
  12. Require MDNS Service
  13. */
  14. const (
  15. AutoDeleteRecordTime = int64(2592000) //30 days = 2592000 seconds
  16. )
  17. type Discoverer struct {
  18. Host *mdns.MDNSHost
  19. Database *database.Database
  20. LastScanningTime int64
  21. NearbyHosts []*mdns.NetworkHost
  22. d chan bool
  23. t *time.Ticker
  24. }
  25. type HostRecord struct {
  26. Name string
  27. Model string
  28. Version string
  29. UUID string
  30. LastSeenIP []string
  31. MacAddr []string
  32. LastOnline int64
  33. }
  34. //New Discoverer return a nearby Aroz Discover agent
  35. func NewDiscoverer(MDNS *mdns.MDNSHost, Database *database.Database) Discoverer {
  36. //Create a new table for neighbour records
  37. Database.NewTable("neighbour")
  38. return Discoverer{
  39. Host: MDNS,
  40. Database: Database,
  41. LastScanningTime: -1,
  42. NearbyHosts: []*mdns.NetworkHost{},
  43. }
  44. }
  45. //Return a list of NetworkHost with the same domain
  46. func (d *Discoverer) GetNearbyHosts() []*mdns.NetworkHost {
  47. nearbyHosts := []*mdns.NetworkHost{}
  48. for _, host := range d.NearbyHosts {
  49. nearbyHosts = append(nearbyHosts, host)
  50. }
  51. return nearbyHosts
  52. }
  53. //Start Scanning, interval and scna Duration in seconds
  54. func (d *Discoverer) StartScanning(interval int, scanDuration int) {
  55. log.Println("ArozOS Neighbour Scanning Started")
  56. if d.ScannerRunning() {
  57. //Another scanner already running. Terminate it
  58. d.StopScanning()
  59. }
  60. //Create a new ticker with the given interval and duration
  61. ticker := time.NewTicker(time.Duration(interval) * time.Second)
  62. done := make(chan bool)
  63. //Start scanner routine
  64. go func() {
  65. for {
  66. select {
  67. case <-done:
  68. return
  69. case <-ticker.C:
  70. d.UpdateScan(scanDuration)
  71. }
  72. }
  73. }()
  74. //Update the Discoverer settings
  75. d.d = done
  76. d.t = ticker
  77. }
  78. func (d *Discoverer) UpdateScan(scanDuration int) {
  79. d.LastScanningTime = time.Now().Unix()
  80. results := d.Host.Scan(scanDuration, d.Host.Host.Domain)
  81. d.NearbyHosts = results
  82. //Record all scanned host into database
  83. for _, thisHost := range results {
  84. thisHostIpString := []string{}
  85. for _, ipaddr := range thisHost.IPv4 {
  86. thisHostIpString = append(thisHostIpString, ipaddr.String())
  87. }
  88. thisHostRecord := HostRecord{
  89. Name: thisHost.HostName,
  90. Model: thisHost.Model,
  91. Version: thisHost.MinorVersion,
  92. UUID: thisHost.UUID,
  93. LastSeenIP: thisHostIpString,
  94. MacAddr: thisHost.MacAddr,
  95. LastOnline: time.Now().Unix(),
  96. }
  97. d.Database.Write("neighbour", thisHost.UUID, thisHostRecord)
  98. }
  99. }
  100. func (d *Discoverer) GetOfflineHosts() ([]*HostRecord, error) {
  101. results := []*HostRecord{}
  102. entries, err := d.Database.ListTable("neighbour")
  103. if err != nil {
  104. return results, err
  105. }
  106. for _, keypairs := range entries {
  107. //Get the host record and UUI from the database
  108. thisHostUUID := string(keypairs[0])
  109. thisHostRecord := HostRecord{}
  110. json.Unmarshal(keypairs[1], &thisHostRecord)
  111. if time.Now().Unix()-thisHostRecord.LastOnline > AutoDeleteRecordTime {
  112. //Remove this record
  113. log.Println("[Neighbour] Removing network host record due to long period offline: " + thisHostUUID + " (" + thisHostRecord.Name + ")")
  114. d.Database.Delete("neighbour", thisHostUUID)
  115. continue
  116. }
  117. //Check this host is online
  118. nodeIsOnline := false
  119. for _, thisOnlineHost := range d.NearbyHosts {
  120. if thisOnlineHost.UUID == thisHostUUID {
  121. //This is online node. skip this
  122. nodeIsOnline = true
  123. break
  124. }
  125. }
  126. if !nodeIsOnline {
  127. results = append(results, &thisHostRecord)
  128. }
  129. }
  130. return results, nil
  131. }
  132. //Try to wake on lan one of the network host
  133. func (d *Discoverer) SendWakeOnLan(macAddr string) error {
  134. return wakeonlan.WakeTarget(macAddr)
  135. }
  136. func (d *Discoverer) ScannerRunning() bool {
  137. if d.d != nil {
  138. return true
  139. } else {
  140. return false
  141. }
  142. }
  143. func (d *Discoverer) StopScanning() {
  144. if d.d != nil {
  145. //Another ticker already running. Terminate it
  146. d.d <- true
  147. //Clear the old ticker
  148. d.t.Stop()
  149. d.d = nil
  150. d.t = nil
  151. }
  152. log.Println("ArozOS Neighbour Scanning Stopped")
  153. }