Class: Bfire::Rule

Inherits:
Object
  • Object
show all
Includes:
PubSub::Publisher
Defined in:
lib/bfire/rule.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from PubSub::Publisher

#error?, #hooks, included, #on, #trigger, #triggered_events

Constructor Details

#initialize(group, opts = {}) ⇒ Rule

Returns a new instance of Rule.



8
9
10
11
# File 'lib/bfire/rule.rb', line 8

def initialize(group, opts = {})
  @group = group
  @opts = {:period => 5*60, :initial => 1, :range => 1..1}.merge(opts)
end

Instance Attribute Details

#groupObject (readonly)

Returns the value of attribute group.



3
4
5
# File 'lib/bfire/rule.rb', line 3

def group
  @group
end

#optsObject (readonly)

Returns the value of attribute opts.



4
5
6
# File 'lib/bfire/rule.rb', line 4

def opts
  @opts
end

Instance Method Details

#launch_initial_resourcesObject



32
33
34
# File 'lib/bfire/rule.rb', line 32

def launch_initial_resources
  scale(:up, opts[:initial])
end

#manage(vms) ⇒ Object



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
# File 'lib/bfire/rule.rb', line 61

def manage(vms)
  return true if vms.empty?
  group.engine.logger.info "#{group.banner}Monitoring VMs... IPs: #{vms.map{|vm| [vm['name'], (vm['nic'] || []).map{|n| n['ip']}.inspect].join("=")}.join("; ")}."
  vms.each(&:reload)
  if failed = vms.find{|compute| compute['state'] == 'FAILED'}
    group.engine.logger.warn "#{group.banner}Compute #{failed.signature} is in a FAILED state."
    if group.triggered_events.include?(:ready)
      group.trigger :error
    else
      group.trigger :scale_error
    end
  elsif vms.all?{|compute| compute['state'] == 'RUNNING'}
    group.engine.logger.info "#{group.banner}All compute resources are ACTIVE"
    if group.ssh_accessible?(vms)
      group.engine.logger.info "#{group.banner}All compute resources are SSH-able"
      provisioned = group.provision!(vms)
      if group.triggered_events.include?(:ready)
        if provisioned
          group.trigger :scaled_up
        else
          group.trigger :scale_error
        end
      else
        if provisioned
          group.trigger :ready
        else
          group.trigger :error
        end
      end
      monitor
    else
      sleep 20
      manage(vms)
    end
  else
    group.engine.logger.info "#{group.banner}Some compute resources are still PENDING"
    sleep 10
    manage(vms)
  end
end

#monitorObject

we only support round-robin placement for now



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/bfire/rule.rb', line 14

def monitor
  loop do
    sleep opts[:period]
    group.engine.logger.info "#{group.banner}Monitoring group elasticity rule..."
    # this is blocking because we don't want the rule to be triggered
    # too many times.
    if scale_up?
      group.engine.logger.info "#{group.banner}Scaling up!"
      manage(scale(:up))
    elsif scale_down?
      group.engine.logger.info "#{group.banner}Scaling down!"
      manage(scale(:down))
    else
      group.engine.logger.info "#{group.banner}..."
    end
  end
end

#scale(up_or_down, count = 1) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/bfire/rule.rb', line 36

def scale(up_or_down, count = 1)
  new_computes = []
  count.times do |i|
    sorted_templates = group.templates.sort_by{|t| t.instances.length}
    if up_or_down == :down
      vm_to_delete = sorted_templates.last.instances[0]
      if vm_to_delete.nil?
        group.engine.logger.warn "#{group.banner}No resource to delete!"
      else
        group.engine.logger.info "#{group.banner}Removing compute #{vm_to_delete.signature}..."
        if vm_to_delete.delete
          sorted_templates.last.instances.delete vm_to_delete
          group.trigger :scaled_down
        end
      end
    else
      template = sorted_templates.first
      computes = group.engine.launch_compute(template)
      template.instances.push(*computes)
      new_computes.push(*computes)
    end
  end
  new_computes
end

#scale_down?Boolean

Returns:

  • (Boolean)


106
107
108
# File 'lib/bfire/rule.rb', line 106

def scale_down?
  opts[:down] && group.computes.length > opts[:range].begin && opts[:down].call(group.engine)
end

#scale_up?Boolean

Returns:

  • (Boolean)


102
103
104
# File 'lib/bfire/rule.rb', line 102

def scale_up?
  opts[:up] && group.computes.length < opts[:range].end && opts[:up].call(group.engine)
end