Class: Cloudmaster::Instance

Inherits:
Object
  • Object
show all
Defined in:
app/instance.rb

Overview

Holds information about a specific instance. When we create an instance in EC2, we create one of these classes to hold information about the instance. Instances are members of the InstancePool.

Each instance holds the following information:

* id -- instance id
* public_dns -- the public dns name of the instance
* load_estimate -- last reported load -- between 0 and 1
* state -- startup, active, shut_down
* start_time -- (local) time when the instance was started
* last_status_time -- (local) time when the last status was received
* last_timestamp -- (remote) timestamp of last report

The state here differs from the EC2 state. We only track instances in EC@ state pending or running. Our state is controlled by status messages received and by stop policies.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id, public_dns, config) ⇒ Instance

Create an instance object, reflecting some instance that was stated or discovered running. New instance objects know their instance id, their public DNS (once this is known) and their load estimate.



28
29
30
31
32
33
34
35
36
37
38
# File 'app/instance.rb', line 28

def initialize(id, public_dns, config)
  @config = config
  @id = id
  @public_dns = public_dns
  @load_estimate = 0
  @start_time = @status_time = Clock.now
  @active_time = Clock.at(0)
  @state_change_time = Clock.now
  @timestamp = Clock.at(0)
  @state = :startup
end

Instance Attribute Details

#idObject (readonly)

Returns the value of attribute id.



20
21
22
# File 'app/instance.rb', line 20

def id
  @id
end

#load_estimateObject

for testing only



22
23
24
# File 'app/instance.rb', line 22

def load_estimate
  @load_estimate
end

#public_dnsObject

Returns the value of attribute public_dns.



21
22
23
# File 'app/instance.rb', line 21

def public_dns
  @public_dns
end

#stateObject

for testing only



22
23
24
# File 'app/instance.rb', line 22

def state
  @state
end

#state_change_timeObject (readonly)

Returns the value of attribute state_change_time.



20
21
22
# File 'app/instance.rb', line 20

def state_change_time
  @state_change_time
end

#status_timeObject (readonly)

for testing only



23
24
25
# File 'app/instance.rb', line 23

def status_time
  @status_time
end

#timestampObject (readonly)

for testing only



23
24
25
# File 'app/instance.rb', line 23

def timestamp
  @timestamp
end

Instance Method Details

#activateObject

Make the instance active. This is usually done after the instance is shut down, but before it is stopped, it needs to become active again.



142
143
144
# File 'app/instance.rb', line 142

def activate
  update_state(:active)
end

#message_more_recent?(timestamp) ⇒ Boolean

Return true if the given timestamp is more recent than the last. This calculation takes place with times from the sender’s clock. In other words, it is comparing values based on two timestamps created by the message sender.

Returns:

  • (Boolean)


75
76
77
# File 'app/instance.rb', line 75

def message_more_recent?(timestamp)
  ! timestamp.nil? && timestamp > @timestamp
end

#minimum_active_time_elapsed?Boolean

Return true if the instance has been active at least as long as its minimum active time.

Returns:

  • (Boolean)


113
114
115
116
117
# File 'app/instance.rb', line 113

def minimum_active_time_elapsed?
active_time = @config[:minimum_active_time].to_i * 60
return true if active_time <= 0
time_since_active > active_time
end

#minimum_lifetime_elapsed?Boolean

Return true if the instance has lived at least as long as its minimum lifetime.

Returns:

  • (Boolean)


105
106
107
108
109
# File 'app/instance.rb', line 105

def minimum_lifetime_elapsed?
lifetime = @config[:minimum_lifetime].to_i * 60
return true if lifetime <= 0
time_since_startup > lifetime
end

#minimum_time_elapsed?Boolean

Return true if the instance has lived and has been active for its respective minimum times.

Returns:

  • (Boolean)


121
122
123
# File 'app/instance.rb', line 121

def minimum_time_elapsed?
  minimum_lifetime_elapsed? && minimum_active_time_elapsed?
end

#reportObject

Return a report of the instance’s state, load estimate, and time since the last status message was received.



42
43
44
# File 'app/instance.rb', line 42

def report
  "State: #{@state} Load: #{sprintf("%.2f", @load_estimate)} Time Since Status: #{time_since_status.round}"
end

#shutdownObject

Shut down an instance by putting it in the “shut_down” state. After this is can either be activated again or stopped.



135
136
137
# File 'app/instance.rb', line 135

def shutdown
  update_state(:shut_down)
end

#time_since_activeObject

Return the number of seconds since the instance became active.



97
98
99
# File 'app/instance.rb', line 97

def time_since_active
  Clock.now - @active_time
end

#time_since_startupObject

Return the number of seconds since the instance was started.



92
93
94
# File 'app/instance.rb', line 92

def time_since_startup
  Clock.now - @start_time
end

#time_since_state_changeObject

Return the number of seconds since the last status message with a state field in it. This uses local times only.



87
88
89
# File 'app/instance.rb', line 87

def time_since_state_change
  Clock.now - @state_change_time
end

#time_since_statusObject

Return the number of seconds since the last message was received. This uses local time only.



81
82
83
# File 'app/instance.rb', line 81

def time_since_status
  Clock.now - @status_time
end

#update_state(state) ⇒ Object



46
47
48
49
50
51
52
53
54
# File 'app/instance.rb', line 46

def update_state(state)
  old_state, @state = @state, state
  @state_change_time = Clock.now
  if old_state != :active && @state == :active
  @active_time = Clock.now
  elsif @old_state == :active && @state != :active
  @active_time = Clock.at(0)
  end
end

#update_status(msg) ⇒ Object

Update the state and estimated load based on status message Ignore the status message if it was sent earlier than one we have already processed. This is important, because SQS routinely delivers messages out of order.



60
61
62
63
64
65
66
67
# File 'app/instance.rb', line 60

def update_status(msg)
  if message_more_recent?(msg[:timestamp])
    @timestamp = msg[:timestamp]
    @status_time = Clock.now
  update_state(msg[:state].to_sym) if msg[:state] 
    @load_estimate = msg[:load_estimate] if msg[:load_estimate]
  end
end

#watchdog_time_elapsed?Boolean

Return true if the instance has not received a status message in the watchdog interval.

Returns:

  • (Boolean)


127
128
129
130
131
# File 'app/instance.rb', line 127

def watchdog_time_elapsed?
  interval = @config[:watchdog_interval].to_i * 60
  return false if interval <= 0
  time_since_status > interval
end