/usr/share/gocode/src/github.com/ctdk/goiardi/node/status.go is in golang-github-ctdk-goiardi-dev 0.11.2-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | /*
* Copyright (c) 2013-2016, Jeremy Bingham (<jeremy@goiardi.gl>)
*
* 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.
*/
// Structs, functions, and methods to record and report on a node's status.
// Goes with the shovey functions and the serf stuff.
package node
import (
"fmt"
"os"
"time"
"github.com/ctdk/goiardi/config"
"github.com/ctdk/goiardi/datastore"
"github.com/tideland/golib/logger"
)
// NodeStatus records a node's status at a particular time.
type NodeStatus struct {
Node *Node
Status string
UpdatedAt time.Time
}
// UpdateStatus updates a node's current status (up, down, or new).
func (n *Node) UpdateStatus(status string) error {
if status != "new" && status != "up" && status != "down" {
err := fmt.Errorf("invalid node status %s", status)
return err
}
s := &NodeStatus{Node: n, Status: status}
if config.UsingDB() {
return s.updateNodeStatusSQL()
}
var nodeDown bool
if status == "down" {
nodeDown = true
}
if nodeDown != n.isDown {
n.isDown = nodeDown
n.Save()
}
s.UpdatedAt = time.Now()
ds := datastore.New()
return ds.SetNodeStatus(n.Name, s)
}
// ImportStatus is used by the import function to import node statuses from the
// exported JSON dump.
func ImportStatus(nodeJSON map[string]interface{}) error {
n := nodeJSON["Node"].(map[string]interface{})
status := nodeJSON["Status"].(string)
ut := nodeJSON["UpdatedAt"].(string)
updatedAt, err := time.Parse(time.RFC3339, ut)
if err != nil {
return err
}
nodeP, err := Get(n["name"].(string))
if err != nil {
return nil
}
ns := &NodeStatus{Node: nodeP, Status: status, UpdatedAt: updatedAt}
if config.UsingDB() {
return ns.importNodeStatus()
}
ds := datastore.New()
nodeP.Save()
return ds.SetNodeStatus(nodeP.Name, ns)
}
// LatestStatus returns the node's latest status.
func (n *Node) LatestStatus() (*NodeStatus, error) {
if config.UsingDB() {
return n.latestStatusSQL()
}
ds := datastore.New()
s, err := ds.LatestNodeStatus(n.Name)
if err != nil {
return nil, err
}
ns := s.(*NodeStatus)
return ns, nil
}
// AllStatuses returns all of the node's status reports to date.
func (n *Node) AllStatuses() ([]*NodeStatus, error) {
if config.UsingDB() {
return n.allStatusesSQL()
}
ds := datastore.New()
arr, err := ds.AllNodeStatuses(n.Name)
if err != nil {
return nil, err
}
ns := make([]*NodeStatus, len(arr))
for i, v := range arr {
ns[i] = v.(*NodeStatus)
}
return ns, nil
}
// AllNodeStatuses returns all node status reports on the server, from all
// nodes.
func AllNodeStatuses() []*NodeStatus {
var allStatus []*NodeStatus
nodes := AllNodes()
for _, n := range nodes {
ns, err := n.AllStatuses()
if err != nil {
logger.Criticalf(err.Error())
os.Exit(1)
}
allStatus = append(allStatus, ns...)
}
return allStatus
}
func (n *Node) deleteStatuses() error {
if config.UsingDB() {
err := fmt.Errorf("not needed in SQL mode - foreign keys handle deleting node statuses")
return err
}
ds := datastore.New()
return ds.DeleteNodeStatus(n.Name)
}
// ToJSON formats a node status report for export to JSON.
func (ns *NodeStatus) ToJSON() map[string]string {
nsmap := make(map[string]string)
nsmap["node_name"] = ns.Node.Name
nsmap["status"] = ns.Status
nsmap["updated_at"] = ns.UpdatedAt.Format(time.RFC3339)
return nsmap
}
// UnseenNodes returns all nodes that have not sent status reports for a while.
func UnseenNodes() ([]*Node, error) {
if config.UsingDB() {
return unseenNodesSQL()
}
var downNodes []*Node
nodes := AllNodes()
t := time.Now().Add(-10 * time.Minute)
for _, n := range nodes {
ns, _ := n.LatestStatus()
if ns == nil || n.isDown {
continue
}
if ns.UpdatedAt.Before(t) {
downNodes = append(downNodes, n)
}
}
return downNodes, nil
}
// GetNodesByStatus returns the nodes that currently have the given status.
func GetNodesByStatus(nodeNames []string, status string) ([]*Node, error) {
if config.UsingDB() {
return getNodesByStatusSQL(nodeNames, status)
}
var statNodes []*Node
nodes := make([]*Node, 0, len(nodeNames))
for _, name := range nodeNames {
n, _ := Get(name)
if n != nil {
nodes = append(nodes, n)
}
}
for _, n := range nodes {
ns, _ := n.LatestStatus()
if ns == nil {
logger.Infof("No status found at all for node %s, skipping", n.Name)
continue
}
if ns.Status == status {
statNodes = append(statNodes, n)
}
}
return statNodes, nil
}
|