Class: Bosh::Deployer::InstanceManager

Inherits:
Object
  • Object
show all
Extended by:
Helpers
Includes:
Helpers
Defined in:
lib/deployer/instance_manager.rb,
lib/deployer/instance_manager/aws.rb,
lib/deployer/instance_manager/vcloud.rb,
lib/deployer/instance_manager/vsphere.rb,
lib/deployer/instance_manager/openstack.rb

Direct Known Subclasses

Aws, Openstack, Vcloud, Vsphere

Defined Under Namespace

Classes: Aws, LoggerRenderer, Openstack, Vcloud, Vsphere

Constant Summary

Constants included from Helpers

Helpers::DEPLOYMENTS_FILE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helpers

cloud_plugin, dig_hash, is_tgz?

Constructor Details

#initialize(config) ⇒ InstanceManager

Returns a new instance of InstanceManager.



47
48
49
50
51
52
53
54
55
56
# File 'lib/deployer/instance_manager.rb', line 47

def initialize(config)
  Config.configure(config)

  @state_yml = File.join(config["dir"], DEPLOYMENTS_FILE)
  load_state(config["name"])

  Config.uuid = state.uuid

  @renderer = LoggerRenderer.new
end

Instance Attribute Details

#rendererObject

Returns the value of attribute renderer.



9
10
11
# File 'lib/deployer/instance_manager.rb', line 9

def renderer
  @renderer
end

#stateObject (readonly)

Returns the value of attribute state.



8
9
10
# File 'lib/deployer/instance_manager.rb', line 8

def state
  @state
end

Class Method Details

.create(config) ⇒ Object



34
35
36
37
38
39
40
41
42
43
# File 'lib/deployer/instance_manager.rb', line 34

def create(config)
  plugin = cloud_plugin(config)

  begin
    require "deployer/instance_manager/#{plugin}"
  rescue LoadError
    err "Could not find Provider Plugin: #{plugin}"
  end
  Bosh::Deployer::InstanceManager.const_get(plugin.capitalize).new(config)
end

Instance Method Details

#agentObject



62
63
64
# File 'lib/deployer/instance_manager.rb', line 62

def agent
  Config.agent
end

#applyObject



347
348
349
350
351
352
353
354
355
356
# File 'lib/deployer/instance_manager.rb', line 347

def apply
  agent_stop

  step "Applying micro BOSH spec" do
    update_spec(@apply_spec)
    agent.run_task(:apply, @apply_spec.update(bosh_ip, service_ip))
  end

  agent_start
end

#attach_disk(disk_cid, is_create = false) ⇒ Object

it is up to the caller to save/update disk state info



283
284
285
286
287
288
# File 'lib/deployer/instance_manager.rb', line 283

def attach_disk(disk_cid, is_create=false)
  return unless disk_cid

  cloud.attach_disk(state.vm_cid, disk_cid)
  mount_disk(disk_cid)
end

#attach_missing_diskObject



301
302
303
304
305
# File 'lib/deployer/instance_manager.rb', line 301

def attach_missing_disk
  if state.disk_cid
    attach_disk(state.disk_cid, true)
  end
end

#check_dependenciesObject



366
367
368
# File 'lib/deployer/instance_manager.rb', line 366

def check_dependencies
  # nothing to check, move on...
end

#check_persistent_diskObject



307
308
309
310
311
312
313
314
315
# File 'lib/deployer/instance_manager.rb', line 307

def check_persistent_disk
  return if state.disk_cid.nil?
  agent_disk_cid = disk_info.first
  if agent_disk_cid != state.disk_cid
    err "instance #{state.vm_cid} has invalid disk: " +
      "Agent reports #{agent_disk_cid} while " +
      "deployer's record shows #{state.disk_cid}"
  end
end

#cloudObject



58
59
60
# File 'lib/deployer/instance_manager.rb', line 58

def cloud
  Config.cloud
end

#create(stemcell_tgz) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/deployer/instance_manager.rb', line 120

def create(stemcell_tgz)
  err "VM #{state.vm_cid} already exists" if state.vm_cid
  if state.stemcell_cid && state.stemcell_cid != state.stemcell_name
    err "stemcell #{state.stemcell_cid} already exists"
  end

  renderer.enter_stage("Deploy Micro BOSH", 11)

  state.stemcell_cid = create_stemcell(stemcell_tgz)
  state.stemcell_name = File.basename(stemcell_tgz, ".tgz")
  save_state

  begin
    step "Creating VM from #{state.stemcell_cid}" do
      state.vm_cid = create_vm(state.stemcell_cid)
      discover_bosh_ip
    end
    save_state
  rescue => e
    # only delete the stemcell if we were trying to upload it
    delete_stemcell if is_tgz?(stemcell_tgz)
    raise e
  end

  step "Waiting for the agent" do
    wait_until_agent_ready
  end

  step "Updating persistent disk" do
    update_persistent_disk
  end

  unless @apply_spec
    step "Fetching apply spec" do
      @apply_spec = Specification.new(agent.release_apply_spec)
    end
  end

  apply

  step "Waiting for the director" do
    wait_until_director_ready
  end
end

#create_deployment(stemcell_tgz) ⇒ Object



102
103
104
105
106
# File 'lib/deployer/instance_manager.rb', line 102

def create_deployment(stemcell_tgz)
  with_lifecycle do
    create(stemcell_tgz)
  end
end

#create_diskObject



255
256
257
258
259
260
261
# File 'lib/deployer/instance_manager.rb', line 255

def create_disk
  step "Create disk" do
    size = Config.resources['persistent_disk']
    state.disk_cid = cloud.create_disk(size, state.vm_cid)
    save_state
  end
end

#create_stemcell(stemcell_tgz) ⇒ Object



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/deployer/instance_manager.rb', line 192

def create_stemcell(stemcell_tgz)
  unless is_tgz?(stemcell_tgz)
    step "Using existing stemcell" do
    end

    return stemcell_tgz
  end

  Dir.mktmpdir("sc-") do |stemcell|
    step "Unpacking stemcell" do
      run_command("tar -zxf #{stemcell_tgz} -C #{stemcell}")
    end

    @apply_spec = Specification.load_from_stemcell(stemcell)

    # load properties from stemcell manifest
    properties = load_stemcell_manifest(stemcell)

    # override with values from the deployment manifest
    override = Config.cloud_options["properties"]["stemcell"]
    properties["cloud_properties"].merge!(override) if override

    step "Uploading stemcell" do
      cloud.create_stemcell("#{stemcell}/image", properties["cloud_properties"])
    end
  end
end

#create_vm(stemcell_cid) ⇒ Object



220
221
222
223
224
225
# File 'lib/deployer/instance_manager.rb', line 220

def create_vm(stemcell_cid)
  resources = Config.resources['cloud_properties']
  networks  = Config.networks
  env = Config.env
  cloud.create_vm(state.uuid, stemcell_cid, resources, networks, nil, env)
end

#delete_deploymentObject



114
115
116
117
118
# File 'lib/deployer/instance_manager.rb', line 114

def delete_deployment
  with_lifecycle do
    destroy
  end
end

#delete_disk(disk_cid, vm_cid) ⇒ Object

it is up to the caller to save/update disk state info



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/deployer/instance_manager.rb', line 264

def delete_disk(disk_cid, vm_cid)
  unmount_disk(disk_cid)

  begin
    step "Detach disk" do
      cloud.detach_disk(vm_cid, disk_cid) if vm_cid
    end
  rescue Bosh::Clouds::DiskNotAttached
  end

  begin
    step "Delete disk" do
      cloud.delete_disk(disk_cid)
    end
  rescue Bosh::Clouds::DiskNotFound
  end
end

#destroyObject



165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/deployer/instance_manager.rb', line 165

def destroy
  renderer.enter_stage("Delete micro BOSH", 7)
  agent_stop
  if state.disk_cid
    step "Deleting persistent disk `#{state.disk_cid}'" do
      delete_disk(state.disk_cid, state.vm_cid)
      state.disk_cid = nil
      save_state
    end
  end
  delete_vm
  delete_stemcell
end

#detach_disk(disk_cid) ⇒ Object



290
291
292
293
294
295
296
297
298
299
# File 'lib/deployer/instance_manager.rb', line 290

def detach_disk(disk_cid)
  unless disk_cid
    err "Error: nil value given for persistent disk id"
  end

  unmount_disk(disk_cid)
  step "Detach disk" do
    cloud.detach_disk(state.vm_cid, disk_cid)
  end
end

#discover_bosh_ipObject



358
359
360
# File 'lib/deployer/instance_manager.rb', line 358

def discover_bosh_ip
  bosh_ip
end

#disk_infoObject



250
251
252
253
# File 'lib/deployer/instance_manager.rb', line 250

def disk_info
  return @disk_list if @disk_list
  @disk_list = agent.list_disk
end

#disk_modelObject



70
71
72
# File 'lib/deployer/instance_manager.rb', line 70

def disk_model
  nil
end

#disk_size(cid) ⇒ Integer

Returns size in MiB.

Returns:

  • (Integer)

    size in MiB



29
30
31
# File 'lib/deployer/instance_manager/vsphere.rb', line 29

def disk_size(cid)
  disk_model.first(:uuid => cid).size
end

#exists?Boolean

Returns:

  • (Boolean)


78
79
80
# File 'lib/deployer/instance_manager.rb', line 78

def exists?
  state.vm_cid != nil
end

#instance_modelObject



74
75
76
# File 'lib/deployer/instance_manager.rb', line 74

def instance_model
  Models::Instance
end

#loggerObject



66
67
68
# File 'lib/deployer/instance_manager.rb', line 66

def logger
  Config.logger
end

#migrate_disk(src_disk_cid, dst_disk_cid) ⇒ Object



244
245
246
247
248
# File 'lib/deployer/instance_manager.rb', line 244

def migrate_disk(src_disk_cid, dst_disk_cid)
  step "Migrate disk" do
    agent.run_task(:migrate_disk, src_disk_cid.to_s, dst_disk_cid.to_s)
  end
end

#mount_disk(disk_cid) ⇒ Object



227
228
229
230
231
# File 'lib/deployer/instance_manager.rb', line 227

def mount_disk(disk_cid)
  step "Mount disk" do
    agent.run_task(:mount_disk, disk_cid.to_s)
  end
end

#persistent_disk_changed?Boolean

Returns:

  • (Boolean)


33
34
35
# File 'lib/deployer/instance_manager/vsphere.rb', line 33

def persistent_disk_changed?
  Config.resources["persistent_disk"] != disk_size(state.disk_cid)
end

#service_ipObject



362
363
364
# File 'lib/deployer/instance_manager.rb', line 362

def service_ip
  bosh_ip
end

#startObject



89
90
# File 'lib/deployer/instance_manager.rb', line 89

def start
end

#step(task) ⇒ Object



82
83
84
85
86
87
# File 'lib/deployer/instance_manager.rb', line 82

def step(task)
  renderer.update(:started, task)
  result = yield
  renderer.update(:finished, task)
  result
end

#stopObject



92
93
# File 'lib/deployer/instance_manager.rb', line 92

def stop
end

#unmount_disk(disk_cid) ⇒ Object



233
234
235
236
237
238
239
240
241
242
# File 'lib/deployer/instance_manager.rb', line 233

def unmount_disk(disk_cid)
  step "Unmount disk" do
    if disk_info.include?(disk_cid)
      agent.run_task(:unmount_disk, disk_cid.to_s)
    else
      logger.error("not unmounting %s as it doesn't belong to me: %s" %
        [disk_cid, disk_info])
    end
  end
end

#update(stemcell_tgz) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/deployer/instance_manager.rb', line 179

def update(stemcell_tgz)
  renderer.enter_stage("Prepare for update", 5)
  agent_stop
  detach_disk(state.disk_cid)
  delete_vm
  # Do we always want to delete the stemcell?
  # What if we are redeploying to the same stemcell version just so
  # we can upgrade to a bigger persistent disk.
  # Perhaps use "--preserve" to skip the delete?
  delete_stemcell
  create(stemcell_tgz)
end

#update_deployment(stemcell_tgz) ⇒ Object



108
109
110
111
112
# File 'lib/deployer/instance_manager.rb', line 108

def update_deployment(stemcell_tgz)
  with_lifecycle do
    update(stemcell_tgz)
  end
end

#update_persistent_diskObject



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/deployer/instance_manager.rb', line 317

def update_persistent_disk
  attach_missing_disk
  check_persistent_disk

  if state.disk_cid.nil?
    create_disk
    attach_disk(state.disk_cid, true)
  elsif persistent_disk_changed?
    size = Config.resources['persistent_disk']

    # save a reference to the old disk
    old_disk_cid = state.disk_cid

    # create a new disk and attach it
    new_disk_cid = cloud.create_disk(size, state.vm_cid)
    attach_disk(new_disk_cid, true)

    # migrate data (which mounts the disks)
    migrate_disk(old_disk_cid, new_disk_cid)

    # replace the old with the new in the state file
    state.disk_cid = new_disk_cid

    # delete the old disk
    delete_disk(old_disk_cid, state.vm_cid)
  end
ensure
  save_state
end

#with_lifecycleObject



95
96
97
98
99
100
# File 'lib/deployer/instance_manager.rb', line 95

def with_lifecycle
  start
  yield
ensure
  stop
end