Class: BigBrother::Cluster

Inherits:
Object
  • Object
show all
Defined in:
lib/big_brother/cluster.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, attributes = {}) ⇒ Cluster

Returns a new instance of Cluster.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/big_brother/cluster.rb', line 5

def initialize(name, attributes = {})
  @name = name
  @fwmark = attributes[:fwmark]
  @scheduler = attributes[:scheduler]
  @check_interval = attributes.fetch(:check_interval, 1)
  @monitored = false
  @nodes = attributes.fetch(:nodes, []).map { |node_config| _coerce_node(node_config) }
  @last_check = Time.new(0)
  @up_file = BigBrother::StatusFile.new('up', @name)
  @down_file = BigBrother::StatusFile.new('down', @name)
  @ramp_up_time = attributes.fetch(:ramp_up_time, 60)
  @has_downpage = attributes[:has_downpage]
  @nagios = attributes[:nagios]
end

Instance Attribute Details

#check_intervalObject (readonly)

Returns the value of attribute check_interval.



3
4
5
# File 'lib/big_brother/cluster.rb', line 3

def check_interval
  @check_interval
end

#fwmarkObject (readonly)

Returns the value of attribute fwmark.



3
4
5
# File 'lib/big_brother/cluster.rb', line 3

def fwmark
  @fwmark
end

#nagiosObject (readonly)

Returns the value of attribute nagios.



3
4
5
# File 'lib/big_brother/cluster.rb', line 3

def nagios
  @nagios
end

#nameObject (readonly)

Returns the value of attribute name.



3
4
5
# File 'lib/big_brother/cluster.rb', line 3

def name
  @name
end

#nodesObject (readonly)

Returns the value of attribute nodes.



3
4
5
# File 'lib/big_brother/cluster.rb', line 3

def nodes
  @nodes
end

#ramp_up_timeObject (readonly)

Returns the value of attribute ramp_up_time.



3
4
5
# File 'lib/big_brother/cluster.rb', line 3

def ramp_up_time
  @ramp_up_time
end

#schedulerObject (readonly)

Returns the value of attribute scheduler.



3
4
5
# File 'lib/big_brother/cluster.rb', line 3

def scheduler
  @scheduler
end

Instance Method Details

#==(other) ⇒ Object



97
98
99
# File 'lib/big_brother/cluster.rb', line 97

def ==(other)
  fwmark == other.fwmark
end

#_add_maintenance_nodeObject



123
124
125
126
# File 'lib/big_brother/cluster.rb', line 123

def _add_maintenance_node
  BigBrother.logger.info "adding 127.0.0.1 to cluster #{self}"
  BigBrother.ipvs.start_node(fwmark, '127.0.0.1', 1)
end

#_add_nodes(addresses) ⇒ Object



116
117
118
119
120
121
# File 'lib/big_brother/cluster.rb', line 116

def _add_nodes(addresses)
  addresses.each do |address|
    BigBrother.logger.info "adding #{address} to cluster #{self}"
    BigBrother.ipvs.start_node(fwmark, address, 100)
  end
end

#_check_downpageObject



128
129
130
131
132
133
134
135
136
137
# File 'lib/big_brother/cluster.rb', line 128

def _check_downpage
  total_health = @nodes.collect{ |n| n.weight || 0 }.reduce(:+)
  if total_health <= 0
    _add_maintenance_node unless downpage_enabled?
    @downpage_enabled = true
  else
    _remove_maintenance_node if downpage_enabled?
    @downpage_enabled = false
  end
end

#_coerce_node(node_config) ⇒ Object



20
21
22
# File 'lib/big_brother/cluster.rb', line 20

def _coerce_node(node_config)
  node_config.is_a?(Node) ? node_config : Node.new(node_config)
end

#_notify_nagiosObject



139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/big_brother/cluster.rb', line 139

def _notify_nagios
  nodes_down = @nodes.count{|n| n.weight == 0}
  return if @last_node_count == nodes_down
  if ((nodes_down / @nodes.count.to_f) >= 0.5)
    BigBrother.nagios.send_critical(nagios[:host], nagios[:check], "50% of nodes are down", nagios[:server])
  elsif nodes_down > 0
    BigBrother.nagios.send_warning(nagios[:host], nagios[:check], "a node is down", nagios[:server])
  else
    BigBrother.nagios.send_ok(nagios[:host], nagios[:check], "all nodes up", nagios[:server])
  end
  @last_node_count = nodes_down
end

#_remove_maintenance_nodeObject



152
153
154
# File 'lib/big_brother/cluster.rb', line 152

def _remove_maintenance_node
  BigBrother.ipvs.stop_node(fwmark, '127.0.0.1')
end

#_remove_nodes(addresses) ⇒ Object



156
157
158
159
160
161
# File 'lib/big_brother/cluster.rb', line 156

def _remove_nodes(addresses)
  addresses.each do |address|
    BigBrother.logger.info "removing #{address} to cluster #{self}"
    BigBrother.ipvs.stop_node(fwmark, address)
  end
end

#combined_weightObject



24
25
26
# File 'lib/big_brother/cluster.rb', line 24

def combined_weight
  nodes.inject(0) { |sum, node| sum + node.weight.to_i }
end

#down_file_exists?Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/big_brother/cluster.rb', line 105

def down_file_exists?
  @down_file.exists?
end

#downpage_enabled?Boolean

Returns:

  • (Boolean)


28
29
30
# File 'lib/big_brother/cluster.rb', line 28

def downpage_enabled?
  @downpage_enabled
end

#find_node(address, port) ⇒ Object



32
33
34
# File 'lib/big_brother/cluster.rb', line 32

def find_node(address, port)
  nodes.find{|node| node.address == address && node.port == port}
end

#has_downpage?Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/big_brother/cluster.rb', line 36

def has_downpage?
  @has_downpage
end

#incorporate_state(another_cluster) ⇒ Object



109
110
111
112
113
114
# File 'lib/big_brother/cluster.rb', line 109

def incorporate_state(another_cluster)
  nodes.each do |node|
    node.incorporate_state(another_cluster.find_node(node.address, node.port))
  end
  self
end

#monitor_nodesObject



85
86
87
88
89
90
91
# File 'lib/big_brother/cluster.rb', line 85

def monitor_nodes
  @last_check = Time.now
  @nodes.each { |node| node.monitor(self) }

  _check_downpage if has_downpage?
  _notify_nagios if nagios
end

#monitored?Boolean

Returns:

  • (Boolean)


40
41
42
# File 'lib/big_brother/cluster.rb', line 40

def monitored?
  @monitored
end

#needs_check?Boolean

Returns:

  • (Boolean)


80
81
82
83
# File 'lib/big_brother/cluster.rb', line 80

def needs_check?
  return false unless monitored?
  @last_check + @check_interval < Time.now
end

#resume_monitoring!Object



62
63
64
65
# File 'lib/big_brother/cluster.rb', line 62

def resume_monitoring!
  BigBrother.logger.info "resuming monitoring on cluster #{to_s}"
  @monitored = true
end

#start_monitoring!Object



44
45
46
47
48
49
50
51
52
# File 'lib/big_brother/cluster.rb', line 44

def start_monitoring!
  BigBrother.logger.info "starting monitoring on cluster #{to_s}"
  BigBrother.ipvs.start_cluster(@fwmark, @scheduler)
  @nodes.each do |node|
    BigBrother.ipvs.start_node(@fwmark, node.address, 100)
  end

  @monitored = true
end

#stop_monitoring!Object



54
55
56
57
58
59
60
# File 'lib/big_brother/cluster.rb', line 54

def stop_monitoring!
  BigBrother.logger.info "stopping monitoring on cluster #{to_s}"
  BigBrother.ipvs.stop_cluster(@fwmark)

  @monitored = false
  @nodes.each(&:invalidate_weight!)
end

#synchronize!Object



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/big_brother/cluster.rb', line 67

def synchronize!
  ipvs_state = BigBrother.ipvs.running_configuration
  if ipvs_state.has_key?(fwmark.to_s)
    resume_monitoring!

    running_nodes = ipvs_state[fwmark.to_s]
    cluster_nodes = nodes.map(&:address)

    _remove_nodes(running_nodes - cluster_nodes)
    _add_nodes(cluster_nodes - running_nodes)
  end
end

#to_sObject



93
94
95
# File 'lib/big_brother/cluster.rb', line 93

def to_s
  "#{@name} (#{@fwmark})"
end

#up_file_exists?Boolean

Returns:

  • (Boolean)


101
102
103
# File 'lib/big_brother/cluster.rb', line 101

def up_file_exists?
  @up_file.exists?
end