Class: Blimpy::Box

Inherits:
Object
  • Object
show all
Includes:
Helpers::State
Defined in:
lib/blimpy/box.rb

Direct Known Subclasses

Blimpy::Boxes::AWS, Blimpy::Boxes::OpenStack

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helpers::State

#ensure_state_folder, #state_folder

Constructor Details

#initialize(server = nil) ⇒ Box

Returns a new instance of Box.



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/blimpy/box.rb', line 35

def initialize(server=nil)
  @provision_on_start = true
  @livery = nil
  @group = nil
  @name = 'Unnamed Box'
  @tags = {}
  @ports = []
  @server = server
  @fleet_id = 0
  @ssh_connected = false
  @exec_commands = true
end

Instance Attribute Details

#allowed_regionsObject (readonly)

Returns the value of attribute allowed_regions.



13
14
15
# File 'lib/blimpy/box.rb', line 13

def allowed_regions
  @allowed_regions
end

#dnsObject

Returns the value of attribute dns.



15
16
17
# File 'lib/blimpy/box.rb', line 15

def dns
  @dns
end

#flavorObject

Returns the value of attribute flavor.



14
15
16
# File 'lib/blimpy/box.rb', line 14

def flavor
  @flavor
end

#fleet_idObject

Returns the value of attribute fleet_id.



16
17
18
# File 'lib/blimpy/box.rb', line 16

def fleet_id
  @fleet_id
end

#groupObject

Returns the value of attribute group.



14
15
16
# File 'lib/blimpy/box.rb', line 14

def group
  @group
end

#image_idObject

Returns the value of attribute image_id.



14
15
16
# File 'lib/blimpy/box.rb', line 14

def image_id
  @image_id
end

#internal_dnsObject

Returns the value of attribute internal_dns.



15
16
17
# File 'lib/blimpy/box.rb', line 15

def internal_dns
  @internal_dns
end

#liveryObject

Returns the value of attribute livery.



16
17
18
# File 'lib/blimpy/box.rb', line 16

def livery
  @livery
end

#nameObject

Returns the value of attribute name.



16
17
18
# File 'lib/blimpy/box.rb', line 16

def name
  @name
end

#portsObject

Returns the value of attribute ports.



14
15
16
# File 'lib/blimpy/box.rb', line 14

def ports
  @ports
end

#provision_on_startObject

Returns the value of attribute provision_on_start.



17
18
19
# File 'lib/blimpy/box.rb', line 17

def provision_on_start
  @provision_on_start
end

#regionObject

Returns the value of attribute region.



13
14
15
# File 'lib/blimpy/box.rb', line 13

def region
  @region
end

#ssh_portObject

Returns the value of attribute ssh_port.



16
17
18
# File 'lib/blimpy/box.rb', line 16

def ssh_port
  @ssh_port
end

#tagsObject

Returns the value of attribute tags.



16
17
18
# File 'lib/blimpy/box.rb', line 16

def tags
  @tags
end

#usernameObject

Returns the value of attribute username.



16
17
18
# File 'lib/blimpy/box.rb', line 16

def username
  @username
end

Class Method Details

.from_instance_id(an_id, data) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/blimpy/box.rb', line 19

def self.from_instance_id(an_id, data)
  return if data[:type].nil?

  name = data[:type].to_sym
  return unless Blimpy::Boxes.const_defined? name

  klass = Blimpy::Boxes.const_get(name)

  server = klass.fog_server_for_instance(an_id, data)
  return if server.nil?

  box = klass.new(server)
  box.with_data(an_id, data)
  box
end

Instance Method Details

#bootstrapObject



77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/blimpy/box.rb', line 77

def bootstrap
  @exec_commands = false
  if @livery.nil?
    return
  end

  if @livery.respond_to? :new
    @livery = @livery.new
  end

  wait_for_sshd
  bootstrap_livery
end

#bootstrap_liveryObject



222
223
224
225
226
227
228
229
230
231
# File 'lib/blimpy/box.rb', line 222

def bootstrap_livery
  if @livery.kind_of? Symbol
    raise Blimpy::InvalidLiveryException, 'Symbol liveries are unsupported!'
  end

  @livery.setup_on(self)
  @livery.preflight(self)
  @livery.flight(self)
  @livery.postflight(self)
end

#destroyObject



111
112
113
114
115
116
117
118
# File 'lib/blimpy/box.rb', line 111

def destroy
  unless @server.nil?
    predestroy
    @server.destroy
    postdestroy
    File.unlink(state_file)
  end
end

#fogObject

Raises:

  • (NotImplementedError)


272
273
274
# File 'lib/blimpy/box.rb', line 272

def fog
  raise NotImplementedError, '#fog should be implemented by cloud-specific subclasses'
end

#immutable_attributesObject



133
134
135
# File 'lib/blimpy/box.rb', line 133

def immutable_attributes
  [:type]
end

#online!Object



55
56
57
# File 'lib/blimpy/box.rb', line 55

def online!
  write_state_file
end

#postdestroyObject



120
121
# File 'lib/blimpy/box.rb', line 120

def postdestroy
end

#poststartObject



74
75
# File 'lib/blimpy/box.rb', line 74

def poststart
end

#predestroyObject



108
109
# File 'lib/blimpy/box.rb', line 108

def predestroy
end

#prestartObject



63
64
# File 'lib/blimpy/box.rb', line 63

def prestart
end

#provisionObject

This is just here to make things more consistent from an API perspective



92
93
94
# File 'lib/blimpy/box.rb', line 92

def provision
  bootstrap
end

#resumeObject



102
103
104
105
106
# File 'lib/blimpy/box.rb', line 102

def resume
  unless @server.nil?
    @server.start
  end
end

#run_command(*args) ⇒ Object



192
193
194
195
196
197
198
# File 'lib/blimpy/box.rb', line 192

def run_command(*args)
  if @exec_commands
    ::Kernel.exec(*args)
  else
    ::Kernel.system(*args)
  end
end

#scp_file(filename, directory = '', *args) ⇒ Object



211
212
213
214
215
# File 'lib/blimpy/box.rb', line 211

def scp_file(filename, directory='', *args)
  filename = File.expand_path(filename)
  run_command('scp', '-o', 'StrictHostKeyChecking=no',
              filename, "#{username}@#{dns}:#{directory}", *args)
end

#scp_files(directory, files) ⇒ Object



217
218
219
220
# File 'lib/blimpy/box.rb', line 217

def scp_files(directory, files)
  filename = File.expand_path(filename)
  run_command(*['scp', '-o', 'StrictHostKeyChecking=no']+files+["#{username}@#{dns}:#{directory}"])
end

#serializable_attributesObject



129
130
131
# File 'lib/blimpy/box.rb', line 129

def serializable_attributes
  [:type, :name, :region, :dns, :internal_dns, :flavor, :tags]
end

#ssh_commands(*args) ⇒ Object



200
201
202
203
204
205
# File 'lib/blimpy/box.rb', line 200

def ssh_commands(*args)
  ['ssh', '-o', 'PasswordAuthentication=no',
      '-o', 'StrictHostKeyChecking=no',
      '-p', (ssh_port||22).to_s,
      '-l', username, dns, *args]
end

#ssh_into(*args) ⇒ Object



207
208
209
# File 'lib/blimpy/box.rb', line 207

def ssh_into(*args)
  run_command(*ssh_commands(*args))
end

#startObject



66
67
68
69
70
71
72
# File 'lib/blimpy/box.rb', line 66

def start
  ensure_state_folder
  prestart
  @server = create_host
  poststart
  write_state_file
end

#state_fileObject



147
148
149
150
151
152
# File 'lib/blimpy/box.rb', line 147

def state_file
  if @server.nil?
    raise Exception, "I can't make a state file without a @server!"
  end
  File.join(state_folder, "#{@server.id}.blimp")
end

#stopObject



96
97
98
99
100
# File 'lib/blimpy/box.rb', line 96

def stop
  unless @server.nil?
    @server.stop
  end
end

#typeObject



123
124
125
126
127
# File 'lib/blimpy/box.rb', line 123

def type
  # We only really care about the class name as part of the Blimpy::Boxes
  # module
  self.class.to_s.split('::').last
end

#validate!Object

Raises:

  • (NotImplementedError)


59
60
61
# File 'lib/blimpy/box.rb', line 59

def validate!
  raise NotImplementedError, '#validate! should be defined in a subclass of Blimpy::Box'
end

#wait_for_sshdObject



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/blimpy/box.rb', line 233

def wait_for_sshd
  return if @ssh_connected
  start = Time.now.to_i
  use_exec = @exec_commands
  # Even if we are supposed to use #exec here, we wait to disable it until
  # after sshd(8) comes online
  @exec_commands = false

  $stdout.sync = true
  need_nl = false

  until @ssh_connected
    # Run the `true` command and exit
    @ssh_connected = ssh_into('-q', 'true')
    # if SSH is killed, don't repeat
    if $?.signaled?
      if $?.termsig==2
        # if Ctrl+C, report what we were doing
        puts "Failed to connect. To try it yourself:\n#{ssh_commands('-v','true').join(' ')}"
      end
      raise Exception, "ssh was killed: #{$?}"
    end

    unless @ssh_connected
      if !need_nl
        p = ssh_port.nil? ? "" : ":#{ssh_port}"
        print ">> Connecting #{username}@#{name}#{p}"
      end
      if (Time.now.to_i - start) < 60
        print '.'
        need_nl = true
        sleep 1
      end
    end
  end
  puts if need_nl
  @exec_commands = use_exec
end

#wait_for_state(until_state, &block) ⇒ Object



154
155
156
157
158
159
160
161
162
163
# File 'lib/blimpy/box.rb', line 154

def wait_for_state(until_state, &block)
  if @server.nil?
    return
  end

  @server.wait_for do
    block.call
    state == until_state
  end
end

#with_data(ship_id, data) ⇒ Object



165
166
167
168
169
170
# File 'lib/blimpy/box.rb', line 165

def with_data(ship_id, data)
  data.each do |key, value|
    next if immutable_attributes.include? key.to_sym
    self.send("#{key}=", value)
  end
end

#write_state_fileObject



137
138
139
140
141
142
143
144
145
# File 'lib/blimpy/box.rb', line 137

def write_state_file
  data = {}
  serializable_attributes.each do |attr|
    data[attr] = self.send(attr)
  end
  File.open(state_file, 'w') do |f|
    f.write(data.to_yaml)
  end
end