neighbour.go 4.2 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. log.Println("ArozOS Neighbour Scanning Completed, ", len(d.NearbyHosts), " neighbours found!")
  78. }
  79. func (d *Discoverer) UpdateScan(scanDuration int) {
  80. d.LastScanningTime = time.Now().Unix()
  81. results := d.Host.Scan(scanDuration, d.Host.Host.Domain)
  82. d.NearbyHosts = results
  83. //Record all scanned host into database
  84. for _, thisHost := range results {
  85. thisHostIpString := []string{}
  86. for _, ipaddr := range thisHost.IPv4 {
  87. thisHostIpString = append(thisHostIpString, ipaddr.String())
  88. }
  89. thisHostRecord := HostRecord{
  90. Name: thisHost.HostName,
  91. Model: thisHost.Model,
  92. Version: thisHost.MinorVersion,
  93. UUID: thisHost.UUID,
  94. LastSeenIP: thisHostIpString,
  95. MacAddr: thisHost.MacAddr,
  96. LastOnline: time.Now().Unix(),
  97. }
  98. d.Database.Write("neighbour", thisHost.UUID, thisHostRecord)
  99. }
  100. }
  101. func (d *Discoverer) GetOfflineHosts() ([]*HostRecord, error) {
  102. results := []*HostRecord{}
  103. entries, err := d.Database.ListTable("neighbour")
  104. if err != nil {
  105. return results, err
  106. }
  107. for _, keypairs := range entries {
  108. //Get the host record and UUI from the database
  109. thisHostUUID := string(keypairs[0])
  110. thisHostRecord := HostRecord{}
  111. json.Unmarshal(keypairs[1], &thisHostRecord)
  112. if time.Now().Unix()-thisHostRecord.LastOnline > AutoDeleteRecordTime {
  113. //Remove this record
  114. log.Println("[Neighbour] Removing network host record due to long period offline: " + thisHostUUID + " (" + thisHostRecord.Name + ")")
  115. d.Database.Delete("neighbour", thisHostUUID)
  116. continue
  117. }
  118. //Check this host is online
  119. nodeIsOnline := false
  120. for _, thisOnlineHost := range d.NearbyHosts {
  121. if thisOnlineHost.UUID == thisHostUUID {
  122. //This is online node. skip this
  123. nodeIsOnline = true
  124. break
  125. }
  126. }
  127. if !nodeIsOnline {
  128. results = append(results, &thisHostRecord)
  129. }
  130. }
  131. return results, nil
  132. }
  133. //Try to wake on lan one of the network host
  134. func (d *Discoverer) SendWakeOnLan(macAddr string) error {
  135. return wakeonlan.WakeTarget(macAddr)
  136. }
  137. func (d *Discoverer) ScannerRunning() bool {
  138. if d.d != nil {
  139. return true
  140. } else {
  141. return false
  142. }
  143. }
  144. func (d *Discoverer) StopScanning() {
  145. if d.d != nil {
  146. //Another ticker already running. Terminate it
  147. d.d <- true
  148. //Clear the old ticker
  149. d.t.Stop()
  150. d.d = nil
  151. d.t = nil
  152. }
  153. log.Println("ArozOS Neighbour Scanning Stopped")
  154. }