Class: BigBrother::ActiveActiveCluster

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

Instance Attribute Summary collapse

Attributes inherited from Cluster

#backend_mode, #check_interval, #fwmark, #nagios, #name, #nodes, #ramp_up_time, #scheduler

Instance Method Summary collapse

Methods inherited from Cluster

#==, #_add_maintenance_node, #_check_downpage, #_coerce_node, #_notify_nagios, #_remove_maintenance_node, #combined_weight, #down_file_exists?, #downpage_enabled?, #find_node, #has_downpage?, #monitored?, #needs_check?, #resume_monitoring!, #to_s, #up_file_exists?

Constructor Details

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

Returns a new instance of ActiveActiveCluster.



5
6
7
8
9
10
11
12
13
14
# File 'lib/big_brother/active_active_cluster.rb', line 5

def initialize(name, attributes={})
  super(name, attributes)
  interpol_nodes, local_nodes = @nodes.partition { |node| node.interpol? }
  @nodes = @local_nodes = local_nodes
  @interpol_node = interpol_nodes.first
  @remote_nodes = []
  @max_down_ticks = attributes.fetch(:max_down_ticks, 0)
  @offset = attributes.fetch(:offset, 10_000)
  @non_egress_locations = *attributes.fetch(:non_egress_locations, [])
end

Instance Attribute Details

#interpol_nodeObject (readonly)

Returns the value of attribute interpol_node.



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

def interpol_node
  @interpol_node
end

#local_nodesObject (readonly)

Returns the value of attribute local_nodes.



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

def local_nodes
  @local_nodes
end

#max_down_ticksObject (readonly)

Returns the value of attribute max_down_ticks.



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

def max_down_ticks
  @max_down_ticks
end

#non_egress_locationsObject (readonly)

Returns the value of attribute non_egress_locations.



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

def non_egress_locations
  @non_egress_locations
end

#offsetObject (readonly)

Returns the value of attribute offset.



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

def offset
  @offset
end

#remote_nodesObject (readonly)

Returns the value of attribute remote_nodes.



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

def remote_nodes
  @remote_nodes
end

Instance Method Details

#_add_nodes(addresses, fwmark) ⇒ Object



104
105
106
107
108
109
# File 'lib/big_brother/active_active_cluster.rb', line 104

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

#_add_remote_nodes(nodes) ⇒ Object



137
138
139
140
141
142
# File 'lib/big_brother/active_active_cluster.rb', line 137

def _add_remote_nodes(nodes)
  nodes.each do |node|
    BigBrother.ipvs.start_node(fwmark, node.address, node.weight)
    @remote_nodes << node
  end
end

#_adjust_or_remove_remote_node(node) ⇒ Object



111
112
113
114
115
116
117
118
119
120
# File 'lib/big_brother/active_active_cluster.rb', line 111

def _adjust_or_remove_remote_node(node)
  if node.down_tick_count >= max_down_ticks
    BigBrother.ipvs.stop_node(fwmark, node.address)
    remote_nodes.delete(node)
  else
    BigBrother.ipvs.edit_node(fwmark, node.address, 0)
    node.weight = 0
    node.down_tick_count += 1
  end
end

#_fetch_remote_nodesObject



122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/big_brother/active_active_cluster.rb', line 122

def _fetch_remote_nodes
  return {} if interpol_node.nil?

  regular_remote_cluster = BigBrother::HealthFetcher.interpol_status(interpol_node, fwmark)
  relay_remote_cluster = BigBrother::HealthFetcher.interpol_status(interpol_node, _relay_fwmark)

  return {} if regular_remote_cluster.empty? || relay_remote_cluster.empty?

  regular_remote_cluster.each_with_object({}) do |node, hsh|
    next if self.non_egress_locations.include?(node['lb_source_location'])

    hsh[node['lb_ip_address']] = BigBrother::Node.new(:address => node['lb_ip_address'], :weight => node['health'])
  end
end

#_relay_fwmarkObject



100
101
102
# File 'lib/big_brother/active_active_cluster.rb', line 100

def _relay_fwmark
  fwmark + offset
end

#_remove_nodes(addresses) ⇒ Object



144
145
146
147
148
149
150
# File 'lib/big_brother/active_active_cluster.rb', line 144

def _remove_nodes(addresses)
  addresses.each do |address|
    BigBrother.logger.info "Removing #{address} from active/active cluster #{self}"
    BigBrother.ipvs.stop_node(fwmark, address)
    BigBrother.ipvs.stop_node(_relay_fwmark, address)
  end
end

#_update_node(node, new_weight) ⇒ Object



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

def _update_node(node, new_weight)
  BigBrother.ipvs.edit_node(fwmark, node.address, new_weight)
  BigBrother.ipvs.edit_node(_relay_fwmark, node.address, new_weight)
end

#cluster_nodesObject



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

def cluster_nodes
  (nodes + remote_nodes).map(&:address)
end

#incorporate_state(cluster) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/big_brother/active_active_cluster.rb', line 71

def incorporate_state(cluster)
  ipvs_state = BigBrother.ipvs.running_configuration
  if ipvs_state[fwmark.to_s] && ipvs_state[_relay_fwmark.to_s].nil?
    BigBrother.logger.info "Adding new active/active LB node #{to_s}"
    BigBrother.ipvs.start_cluster(_relay_fwmark, @scheduler)
  end

  if ipvs_state[fwmark.to_s] && ipvs_state.fetch(_relay_fwmark.to_s, []).empty?
    nodes.each do |node|
      actual_node = cluster.find_node(node.address, node.port)
      BigBrother.ipvs.start_node(_relay_fwmark, actual_node.address, actual_node.weight)
    end
  end

  BigBrother.logger.info "Merging in new active/active cluster #{to_s}"

  @remote_nodes = cluster.remote_nodes if cluster.is_a?(BigBrother::ActiveActiveCluster)

  super(cluster)
end

#local_cluster_nodesObject



67
68
69
# File 'lib/big_brother/active_active_cluster.rb', line 67

def local_cluster_nodes
  nodes.map(&:address)
end

#monitor_nodesObject



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/big_brother/active_active_cluster.rb', line 33

def monitor_nodes
  super

  fresh_remote_nodes = _fetch_remote_nodes
  remote_nodes.each do |node|
    if new_node = fresh_remote_nodes[node.address]
      next if new_node.weight == node.weight
      BigBrother.ipvs.edit_node(fwmark, node.address, new_node.weight)
      node.weight = new_node.weight
    else
      _adjust_or_remove_remote_node(node)
    end
  end

  _add_remote_nodes(fresh_remote_nodes.values - remote_nodes)
end

#start_monitoring!Object



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/big_brother/active_active_cluster.rb', line 16

def start_monitoring!
  BigBrother.logger.info "Starting monitoring on active/active cluster #{to_s}"
  BigBrother.ipvs.start_cluster(@fwmark, @scheduler)
  BigBrother.ipvs.start_cluster(_relay_fwmark, @scheduler)
  local_nodes.each do |node|
    BigBrother.ipvs.start_node(@fwmark, node.address, BigBrother::Node::INITIAL_WEIGHT)
    BigBrother.ipvs.start_node(_relay_fwmark, node.address, BigBrother::Node::INITIAL_WEIGHT)
  end

  @monitored = true
end

#stop_monitoring!Object



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

def stop_monitoring!
  super
  BigBrother.ipvs.stop_cluster(_relay_fwmark)
end

#stop_relay_fwmarkObject



92
93
94
95
96
97
98
# File 'lib/big_brother/active_active_cluster.rb', line 92

def stop_relay_fwmark
  nodes.each do |node|
    BigBrother.ipvs.stop_node(_relay_fwmark, node.address)
  end

  BigBrother.ipvs.stop_cluster(_relay_fwmark)
end

#synchronize!Object



50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/big_brother/active_active_cluster.rb', line 50

def synchronize!
  ipvs_state = BigBrother.ipvs.running_configuration
  @remote_nodes = _fetch_remote_nodes.values if @remote_nodes == []
  if ipvs_state.has_key?(fwmark.to_s)
    resume_monitoring!

    running_nodes = ipvs_state[fwmark.to_s]
    _remove_nodes(running_nodes - cluster_nodes)
    _add_nodes(cluster_nodes - running_nodes, fwmark)
    _add_nodes(local_cluster_nodes - running_nodes, _relay_fwmark)
  end
end