aboutsummaryrefslogtreecommitdiff
path: root/internal/server
diff options
context:
space:
mode:
authorRaúl Benencia <raul@thousandeyes.com>2018-04-13 16:30:31 -0700
committerRaúl Benencia <raul@thousandeyes.com>2018-05-11 15:02:34 -0700
commit77c172b823b64ebface655681ab0749b9d2f7081 (patch)
tree09c13e626eb95ae1d33e76ed683172eab1ab6c96 /internal/server
First public commit
Diffstat (limited to 'internal/server')
-rw-r--r--internal/server/server.go123
1 files changed, 123 insertions, 0 deletions
diff --git a/internal/server/server.go b/internal/server/server.go
new file mode 100644
index 0000000..1bc7e88
--- /dev/null
+++ b/internal/server/server.go
@@ -0,0 +1,123 @@
+// Copyright 2018 ThousandEyes Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package server
+
+import (
+ "sync"
+ "time"
+
+ "github.com/thousandeyes/shoelaces/internal/log"
+)
+
+const (
+ // InitTarget is an initial dummy target assigned to the servers
+ InitTarget = "NOTARGET"
+)
+
+// Server holds data that uniquely identifies a server
+type Server struct {
+ Mac string
+ IP string
+ Hostname string
+}
+
+// Servers is an array of Server
+type Servers []Server
+
+// Len implementation for the sort Interface
+func (s Servers) Len() int {
+ return len(s)
+}
+
+// Swap implementation for the sort interface
+func (s Servers) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+// Less implementation for the Sort interface
+func (s Servers) Less(i, j int) bool {
+ return s[i].Mac < s[j].Mac
+}
+
+// State holds information regarding a host that is attempting to boot.
+type State struct {
+ Server
+ Target string
+ Environment string
+ Params map[string]interface{}
+ Retry int
+ LastAccess int
+}
+
+// States holds a map between MAC addresses and
+// States. It provides a mutex for thread-safety.
+type States struct {
+ sync.RWMutex
+ Servers map[string]*State
+}
+
+// New returns a Server with is values initialized
+func New(mac string, ip string, hostname string) Server {
+ return Server{
+ Mac: mac,
+ IP: ip,
+ Hostname: hostname,
+ }
+}
+
+// AddServer adds a server to the States struct
+func (m *States) AddServer(server Server) {
+ m.Servers[server.Mac] = &State{
+ Server: server,
+ Target: InitTarget,
+ Retry: 1,
+ LastAccess: int(time.Now().UTC().Unix()),
+ }
+}
+
+// DeleteServer deletes a server from the States struct
+func (m *States) DeleteServer(mac string) {
+ delete(m.Servers, mac)
+}
+
+// StartStateCleaner spawns a goroutine that cleans MAC addresses that
+// have been inactive in Shoelaces for more than 3 minutes.
+func StartStateCleaner(logger log.Logger, serverStates *States) {
+ const (
+ // 3 minutes
+ expireAfterSec = 3 * 60
+ cleanInterval = time.Minute
+ )
+ // Clean up the server states. Expire after 3 minutes
+ go func() {
+ for {
+ time.Sleep(cleanInterval)
+
+ servers := serverStates.Servers
+ expire := int(time.Now().UTC().Unix()) - expireAfterSec
+
+ logger.Debug("component", "polling", "msg", "Cleaning", "before", time.Unix(int64(expire), 0))
+
+ serverStates.Lock()
+ for mac, state := range servers {
+ if state.LastAccess <= expire {
+ delete(servers, mac)
+ logger.Debug("component", "polling", "msg", "Mac cleaned", "mac", mac)
+ }
+ }
+ serverStates.Unlock()
+ }
+ }()
+}
nihil fit ex nihilo