vcap_services_base 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/lib/base/abstract.rb +11 -0
  3. data/lib/base/api/message.rb +31 -0
  4. data/lib/base/asynchronous_service_gateway.rb +529 -0
  5. data/lib/base/backup.rb +206 -0
  6. data/lib/base/barrier.rb +54 -0
  7. data/lib/base/base.rb +159 -0
  8. data/lib/base/base_async_gateway.rb +164 -0
  9. data/lib/base/base_job.rb +5 -0
  10. data/lib/base/catalog_manager_base.rb +67 -0
  11. data/lib/base/catalog_manager_v1.rb +225 -0
  12. data/lib/base/catalog_manager_v2.rb +291 -0
  13. data/lib/base/cloud_controller_services.rb +75 -0
  14. data/lib/base/datamapper_l.rb +148 -0
  15. data/lib/base/gateway.rb +167 -0
  16. data/lib/base/gateway_service_catalog.rb +68 -0
  17. data/lib/base/http_handler.rb +101 -0
  18. data/lib/base/job/async_job.rb +71 -0
  19. data/lib/base/job/config.rb +27 -0
  20. data/lib/base/job/lock.rb +153 -0
  21. data/lib/base/job/package.rb +112 -0
  22. data/lib/base/job/serialization.rb +365 -0
  23. data/lib/base/job/snapshot.rb +354 -0
  24. data/lib/base/node.rb +471 -0
  25. data/lib/base/node_bin.rb +154 -0
  26. data/lib/base/plan.rb +63 -0
  27. data/lib/base/provisioner.rb +1120 -0
  28. data/lib/base/provisioner_v1.rb +125 -0
  29. data/lib/base/provisioner_v2.rb +193 -0
  30. data/lib/base/service.rb +93 -0
  31. data/lib/base/service_advertiser.rb +184 -0
  32. data/lib/base/service_error.rb +122 -0
  33. data/lib/base/service_message.rb +94 -0
  34. data/lib/base/service_plan_change_set.rb +11 -0
  35. data/lib/base/simple_aop.rb +63 -0
  36. data/lib/base/snapshot_v2/snapshot.rb +227 -0
  37. data/lib/base/snapshot_v2/snapshot_client.rb +158 -0
  38. data/lib/base/snapshot_v2/snapshot_job.rb +95 -0
  39. data/lib/base/utils.rb +63 -0
  40. data/lib/base/version.rb +7 -0
  41. data/lib/base/warden/instance_utils.rb +161 -0
  42. data/lib/base/warden/node_utils.rb +205 -0
  43. data/lib/base/warden/service.rb +426 -0
  44. data/lib/base/worker_bin.rb +76 -0
  45. data/lib/vcap_services_base.rb +16 -0
  46. metadata +364 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7305761e681e387c91d65dac8b89f8e2b64e8d30
4
+ data.tar.gz: 05c46995ea778aa60afa54f126d04e44fcf4c141
5
+ SHA512:
6
+ metadata.gz: 9f4566a5e13cb08ddec54346c25d94e8ee33fc9274077fe268600444fed05a8ee324ae857b082a13aaececcb9cdf118ef31bb3cb3c15c8af2075c174168f561e
7
+ data.tar.gz: 5471d45f69760f4bf963eda9cfdb4cb51e505e9ec722ef8a4d94a1580086dbd446e86ae82be880426ea72d4ada5cc89fd9c03b12517724497cb66235be4c9b67
@@ -0,0 +1,11 @@
1
+ # Copyright (c) 2009-2011 VMware, Inc.
2
+ class Class
3
+ def abstract(*args)
4
+ args.each do |method_name|
5
+ define_method(method_name) do |*args|
6
+ raise NotImplementedError.new("Unimplemented abstract method #{self.class.name}##{method_name}")
7
+ end
8
+ end
9
+ end
10
+ end
11
+
@@ -0,0 +1,31 @@
1
+ # Copyright (c) 2009-2011 VMware, Inc.
2
+ #
3
+ $:.unshift(File.expand_path("../..", __FILE__))
4
+ require 'json_message'
5
+ require 'base'
6
+
7
+ class ServiceMessage < JsonMessage
8
+
9
+ def set_field(field, value)
10
+ field = field.to_sym
11
+ return unless self.class.fields.has_key?(field)
12
+ f = self.class.fields[field]
13
+ # delete an optional field
14
+ if value.nil? and f.required == false
15
+ @msg.delete(field)
16
+ else
17
+ errs = f.schema.validate(value)
18
+ raise ValidationError.new({field => errs}) if errs
19
+ @msg[field] = value
20
+ end
21
+ end
22
+
23
+ # Return a deep copy of @msg
24
+ def dup
25
+ @msg.deep_dup
26
+ end
27
+
28
+ def inspect
29
+ @msg.inspect
30
+ end
31
+ end
@@ -0,0 +1,529 @@
1
+ # Copyright (c) 2009-2011 VMware, Inc.
2
+ require 'base_async_gateway'
3
+ require 'gateway_service_catalog'
4
+
5
+ $:.unshift(File.dirname(__FILE__))
6
+
7
+ # A simple service gateway that proxies requests onto an asynchronous service provisioners.
8
+ # NB: Do not use this with synchronous provisioners, it will produce unexpected results.
9
+ #
10
+ # TODO(mjp): This needs to handle unknown routes
11
+ module VCAP::Services
12
+ class AsynchronousServiceGateway < BaseAsynchronousServiceGateway
13
+
14
+ REQ_OPTS = %w(service token provisioner cloud_controller_uri).map { |o| o.to_sym }
15
+ attr_reader :event_machine, :logger, :service
16
+
17
+ def initialize(opts)
18
+ super(opts)
19
+ end
20
+
21
+ # setup the environment
22
+ def setup(opts)
23
+ missing_opts = REQ_OPTS.select { |o| !opts.has_key? o }
24
+ raise ArgumentError, "Missing options: #{missing_opts.join(', ')}" unless missing_opts.empty?
25
+ @service = opts[:service]
26
+ @token = opts[:token]
27
+ @logger = opts[:logger] || make_logger()
28
+ @cld_ctrl_uri = http_uri(opts[:cloud_controller_uri])
29
+ @provisioner = opts[:provisioner]
30
+ @hb_interval = opts[:heartbeat_interval] || 60
31
+ @node_timeout = opts[:node_timeout]
32
+ @handle_fetch_interval = opts[:handle_fetch_interval] || 1
33
+ @check_orphan_interval = opts[:check_orphan_interval] || -1
34
+ @double_check_orphan_interval = opts[:double_check_orphan_interval] || 300
35
+ @handle_fetched = opts[:handle_fetched] || false
36
+ @fetching_handles = false
37
+ @version_aliases = (service[:version_aliases] ||= {})
38
+
39
+ opts[:gateway_name] ||= "Service Gateway"
40
+
41
+ @cc_api_version = opts[:cc_api_version] || "v1"
42
+ if @cc_api_version == "v1"
43
+ require 'catalog_manager_v1'
44
+ @catalog_manager = VCAP::Services::CatalogManagerV1.new(opts)
45
+ elsif @cc_api_version == "v2"
46
+ require 'catalog_manager_v2'
47
+ @catalog_manager = VCAP::Services::CatalogManagerV2.new(opts)
48
+ else
49
+ raise "Unknown cc_api_version: #{@cc_api_version}"
50
+ end
51
+
52
+ @event_machine = opts[:event_machine] || EM
53
+
54
+ # Setup heartbeats and exit handlers
55
+ event_machine.add_periodic_timer(@hb_interval) { send_heartbeat }
56
+ event_machine.next_tick { send_heartbeat }
57
+ Kernel.at_exit do
58
+ if event_machine.reactor_running?
59
+ # :/ We can't stop others from killing the event-loop here. Let's hope that they play nice
60
+ send_deactivation_notice(false)
61
+ else
62
+ event_machine.run { send_deactivation_notice }
63
+ end
64
+ end
65
+
66
+ # Add any necessary handles we don't know about
67
+ update_callback = Proc.new do |resp|
68
+ @provisioner.update_handles(resp.handles)
69
+ @handle_fetched = true
70
+ event_machine.cancel_timer(@fetch_handle_timer)
71
+
72
+ # TODO remove it when we finish the migration
73
+ current_version = @version_aliases && @version_aliases[:current]
74
+ if current_version
75
+ @provisioner.update_version_info(current_version)
76
+ else
77
+ logger.info("No current version alias is supplied, skip update version in CCDB.")
78
+ end
79
+ end
80
+
81
+ @fetch_handle_timer = event_machine.add_periodic_timer(@handle_fetch_interval) { fetch_handles(&update_callback) }
82
+ event_machine.next_tick { fetch_handles(&update_callback) }
83
+
84
+ if @check_orphan_interval > 0
85
+ handler_check_orphan = Proc.new do |resp|
86
+ check_orphan(resp.handles,
87
+ lambda { logger.info("Check orphan is requested") },
88
+ lambda { |errmsg| logger.error("Error on requesting to check orphan #{errmsg}") })
89
+ end
90
+ event_machine.add_periodic_timer(@check_orphan_interval) { fetch_handles(&handler_check_orphan) }
91
+ end
92
+
93
+ # Register update handle callback
94
+ @provisioner.register_update_handle_callback { |handle, &blk| update_service_handle(handle, &blk) }
95
+ end
96
+
97
+ def get_current_catalog
98
+ GatewayServiceCatalog.new([service]).to_hash
99
+ end
100
+
101
+ def check_orphan(handles, callback, errback)
102
+ @provisioner.check_orphan(handles) do |msg|
103
+ if msg['success']
104
+ callback.call
105
+ event_machine.add_timer(@double_check_orphan_interval) { fetch_handles { |rs| @provisioner.double_check_orphan(rs.handles) } }
106
+ else
107
+ errback.call(msg['response'])
108
+ end
109
+ end
110
+ end
111
+
112
+ # Validate the incoming request
113
+ def validate_incoming_request
114
+ unless request.media_type == Rack::Mime.mime_type('.json')
115
+ error_msg = ServiceError.new(ServiceError::INVALID_CONTENT).to_hash
116
+ logger.error("Validation failure: #{error_msg.inspect}, request media type: #{request.media_type} is not json")
117
+ abort_request(error_msg)
118
+ end
119
+ unless auth_token && (auth_token == @token)
120
+ error_msg = ServiceError.new(ServiceError::NOT_AUTHORIZED).to_hash
121
+ logger.error("Validation failure: #{error_msg.inspect}, expected token: #{@token}, specified token: #{auth_token}")
122
+ abort_request(error_msg)
123
+ end
124
+ unless @handle_fetched
125
+ error_msg = ServiceError.new(ServiceError::SERVICE_UNAVAILABLE).to_hash
126
+ logger.error("Validation failure: #{error_msg.inspect}, handles not fetched")
127
+ abort_request(error_msg)
128
+ end
129
+ end
130
+
131
+ #################### Handlers ####################
132
+
133
+ # Provisions an instance of the service
134
+ #
135
+ post '/gateway/v1/configurations' do
136
+ req = VCAP::Services::Api::GatewayProvisionRequest.decode(request_body)
137
+ @logger.debug("Provision request for unique_id=#{req.unique_id}")
138
+
139
+ unless plan_exists?(req)
140
+ error_msg = ServiceError.new(ServiceError::UNKNOWN_PLAN_UNIQUE_ID).to_hash
141
+ abort_request(error_msg)
142
+ end
143
+
144
+ @provisioner.provision_service(req) do |msg|
145
+ if msg['success']
146
+ async_reply(VCAP::Services::Api::GatewayHandleResponse.new(msg['response']).encode)
147
+ else
148
+ async_reply_error(msg['response'])
149
+ end
150
+ end
151
+ async_mode
152
+ end
153
+
154
+ # Unprovisions a previously provisioned instance of the service
155
+ #
156
+ delete '/gateway/v1/configurations/:service_id' do
157
+ logger.debug("Unprovision request for service_id=#{params['service_id']}")
158
+
159
+ @provisioner.unprovision_service(params['service_id']) do |msg|
160
+ if msg['success']
161
+ async_reply
162
+ else
163
+ async_reply_error(msg['response'])
164
+ end
165
+ end
166
+ async_mode
167
+ end
168
+
169
+ # Binds a previously provisioned instance of the service to an application
170
+ #
171
+ post '/gateway/v1/configurations/:service_id/handles' do
172
+ logger.info("Binding request for service=#{params['service_id']}")
173
+
174
+ req = VCAP::Services::Api::GatewayBindRequest.decode(request_body)
175
+ logger.debug("Binding request: #{req.extract}")
176
+
177
+ @provisioner.bind_instance(req.service_id, req.binding_options) do |msg|
178
+ if msg['success']
179
+ async_reply(VCAP::Services::Api::GatewayHandleResponse.new(msg['response']).encode)
180
+ else
181
+ async_reply_error(msg['response'])
182
+ end
183
+ end
184
+ async_mode
185
+ end
186
+
187
+ # Unbinds a previously bound instance of the service
188
+ #
189
+ delete '/gateway/v1/configurations/:service_id/handles/:handle_id' do
190
+ logger.info("Unbind request for service_id={params['service_id']} handle_id=#{params['handle_id']}")
191
+
192
+ req = VCAP::Services::Api::GatewayUnbindRequest.decode(request_body)
193
+
194
+ @provisioner.unbind_instance(req.service_id, req.handle_id, req.binding_options) do |msg|
195
+ if msg['success']
196
+ async_reply
197
+ else
198
+ async_reply_error(msg['response'])
199
+ end
200
+ end
201
+ async_mode
202
+ end
203
+
204
+ post "/gateway/v2/configurations/:service_id/snapshots" do
205
+ service_id = params["service_id"]
206
+ name = Yajl::Parser.parse(request_body).fetch('name')
207
+
208
+ @provisioner.create_snapshot_v2(service_id, name) do |msg|
209
+ if msg['success']
210
+ async_reply(VCAP::Services::Api::SnapshotV2.new(msg['response']).encode)
211
+ else
212
+ async_reply_error(msg['response'])
213
+ end
214
+ end
215
+ async_mode
216
+ end
217
+
218
+ # create a snapshot
219
+ post "/gateway/v1/configurations/:service_id/snapshots" do
220
+ service_id = params["service_id"]
221
+ @provisioner.create_snapshot(service_id) do |msg|
222
+ if msg['success']
223
+ async_reply(VCAP::Services::Api::Job.new(msg['response']).encode)
224
+ else
225
+ async_reply_error(msg['response'])
226
+ end
227
+ async_reply
228
+ end
229
+ async_mode
230
+ end
231
+
232
+ # Get snapshot details
233
+ get "/gateway/v1/configurations/:service_id/snapshots/:snapshot_id" do
234
+ service_id = params["service_id"]
235
+ snapshot_id = params["snapshot_id"]
236
+ logger.info("Get snapshot_id=#{snapshot_id} request for service_id=#{service_id}")
237
+ @provisioner.get_snapshot(service_id, snapshot_id) do |msg|
238
+ if msg['success']
239
+ async_reply(VCAP::Services::Api::Snapshot.new(msg['response']).encode)
240
+ else
241
+ async_reply_error(msg['response'])
242
+ end
243
+ end
244
+ async_mode
245
+ end
246
+
247
+ # Update snapshot name
248
+ post "/gateway/v1/configurations/:service_id/snapshots/:snapshot_id/name" do
249
+ req = VCAP::Services::Api::UpdateSnapshotNameRequest.decode(request_body)
250
+ service_id = params["service_id"]
251
+ snapshot_id = params["snapshot_id"]
252
+ logger.info("Update name of snapshot=#{snapshot_id} for service_id=#{service_id} to '#{req.name}'")
253
+ @provisioner.update_snapshot_name(service_id, snapshot_id, req.name) do |msg|
254
+ if msg['success']
255
+ async_reply
256
+ else
257
+ async_reply_error(msg['response'])
258
+ end
259
+ end
260
+ async_mode
261
+ end
262
+
263
+ # Enumerate snapshot
264
+ get "/gateway/v1/configurations/:service_id/snapshots" do
265
+ service_id = params["service_id"]
266
+ logger.info("Enumerate snapshots request for service_id=#{service_id}")
267
+ @provisioner.enumerate_snapshots(service_id) do |msg|
268
+ if msg['success']
269
+ async_reply(VCAP::Services::Api::SnapshotList.new(msg['response']).encode)
270
+ else
271
+ async_reply_error(msg['response'])
272
+ end
273
+ end
274
+ async_mode
275
+ end
276
+
277
+ get "/gateway/v2/configurations/:service_id/snapshots" do
278
+ service_id = params["service_id"]
279
+ logger.info("Enumerate snapshots request for service_id=#{service_id}")
280
+ @provisioner.enumerate_snapshots_v2(params["service_id"]) do |msg|
281
+ if msg['success']
282
+ async_reply(VCAP::Services::Api::SnapshotListV2.new(:snapshots => msg['response']).encode)
283
+ else
284
+ async_reply_error(msg['response'])
285
+ end
286
+ end
287
+ async_mode
288
+ end
289
+
290
+ # Rollback to a snapshot
291
+ put "/gateway/v1/configurations/:service_id/snapshots/:snapshot_id" do
292
+ service_id = params["service_id"]
293
+ snapshot_id = params["snapshot_id"]
294
+ logger.info("Rollback service_id=#{service_id} to snapshot_id=#{snapshot_id}")
295
+ @provisioner.rollback_snapshot(service_id, snapshot_id) do |msg|
296
+ if msg['success']
297
+ async_reply(VCAP::Services::Api::Job.new(msg['response']).encode)
298
+ else
299
+ async_reply_error(msg['response'])
300
+ end
301
+ end
302
+ async_mode
303
+ end
304
+
305
+ # Delete a snapshot
306
+ delete "/gateway/v1/configurations/:service_id/snapshots/:snapshot_id" do
307
+ service_id = params["service_id"]
308
+ snapshot_id = params["snapshot_id"]
309
+ logger.info("Delete service_id=#{service_id} to snapshot_id=#{snapshot_id}")
310
+ @provisioner.delete_snapshot(service_id, snapshot_id) do |msg|
311
+ if msg['success']
312
+ async_reply(VCAP::Services::Api::Job.new(msg['response']).encode)
313
+ else
314
+ async_reply_error(msg['response'])
315
+ end
316
+ end
317
+ async_mode
318
+ end
319
+
320
+ # Create a serialized url for a service snapshot
321
+ post "/gateway/v1/configurations/:service_id/serialized/url/snapshots/:snapshot_id" do
322
+ service_id = params["service_id"]
323
+ snapshot_id = params["snapshot_id"]
324
+ logger.info("Create serialized url for snapshot=#{snapshot_id} of service_id=#{service_id} ")
325
+ @provisioner.create_serialized_url(service_id, snapshot_id) do |msg|
326
+ if msg['success']
327
+ async_reply(VCAP::Services::Api::Job.new(msg['response']).encode)
328
+ else
329
+ async_reply_error(msg['response'])
330
+ end
331
+ end
332
+ async_mode
333
+ end
334
+
335
+ # Get serialized url for a service snapshot
336
+ get "/gateway/v1/configurations/:service_id/serialized/url/snapshots/:snapshot_id" do
337
+ service_id = params["service_id"]
338
+ snapshot_id = params["snapshot_id"]
339
+ logger.info("Get serialized url for snapshot=#{snapshot_id} of service_id=#{service_id} ")
340
+ @provisioner.get_serialized_url(service_id, snapshot_id) do |msg|
341
+ if msg['success']
342
+ async_reply(VCAP::Services::Api::SerializedURL.new(msg['response']).encode)
343
+ else
344
+ async_reply_error(msg['response'])
345
+ end
346
+ end
347
+ async_mode
348
+ end
349
+
350
+ # Import serialized data from url
351
+ put "/gateway/v1/configurations/:service_id/serialized/url" do
352
+ req = VCAP::Services::Api::SerializedURL.decode(request_body)
353
+ service_id = params["service_id"]
354
+ logger.info("Import serialized data from url:#{req.url} for service_id=#{service_id}")
355
+ @provisioner.import_from_url(service_id, req.url) do |msg|
356
+ if msg['success']
357
+ async_reply(VCAP::Services::Api::Job.new(msg['response']).encode)
358
+ else
359
+ async_reply_error(msg['response'])
360
+ end
361
+ end
362
+ async_mode
363
+ end
364
+
365
+ # Get Job details
366
+ get "/gateway/v1/configurations/:service_id/jobs/:job_id" do
367
+ service_id = params["service_id"]
368
+ job_id = params["job_id"]
369
+ logger.info("Get job=#{job_id} for service_id=#{service_id}")
370
+ @provisioner.job_details(service_id, job_id) do |msg|
371
+ if msg['success']
372
+ async_reply(VCAP::Services::Api::Job.new(msg['response']).encode)
373
+ else
374
+ async_reply_error(msg['response'])
375
+ end
376
+ end
377
+ async_mode
378
+ end
379
+
380
+ # Restore an instance of the service
381
+ #
382
+ post '/service/internal/v1/restore' do
383
+ logger.info("Restore service")
384
+
385
+ req = Yajl::Parser.parse(request_body)
386
+ # TODO add json format check
387
+
388
+ @provisioner.restore_instance(req['instance_id'], req['backup_path']) do |msg|
389
+ if msg['success']
390
+ async_reply
391
+ else
392
+ async_reply_error(msg['response'])
393
+ end
394
+ end
395
+ async_mode
396
+ end
397
+
398
+ # Recovery an instance if node is crashed.
399
+ post '/service/internal/v1/recover' do
400
+ logger.info("Recover service request.")
401
+ request = Yajl::Parser.parse(request_body)
402
+ instance_id = request['instance_id']
403
+ backup_path = request['backup_path']
404
+ fetch_handles do |resp|
405
+ @provisioner.recover(instance_id, backup_path, resp.handles) do |msg|
406
+ if msg['success']
407
+ async_reply
408
+ else
409
+ async_reply_error(msg['response'])
410
+ end
411
+ end
412
+ end
413
+ async_mode
414
+ end
415
+
416
+ post '/service/internal/v1/check_orphan' do
417
+ logger.info("Request to check orphan")
418
+ fetch_handles do |resp|
419
+ check_orphan(resp.handles,
420
+ lambda { async_reply },
421
+ lambda { |errmsg| async_reply_error(errmsg) })
422
+ end
423
+ async_mode
424
+ end
425
+
426
+ delete '/service/internal/v1/purge_orphan' do
427
+ logger.info("Purge orphan request")
428
+ req = Yajl::Parser.parse(request_body)
429
+ orphan_ins_hash = req["orphan_instances"]
430
+ orphan_binding_hash = req["orphan_bindings"]
431
+ @provisioner.purge_orphan(orphan_ins_hash, orphan_binding_hash) do |msg|
432
+ if msg['success']
433
+ async_reply
434
+ else
435
+ async_reply_error(msg['response'])
436
+ end
437
+ end
438
+ async_mode
439
+ end
440
+
441
+ # Service migration API
442
+ post "/service/internal/v1/migration/:node_id/:instance_id/:action" do
443
+ logger.info("Migration: #{params["action"]} instance #{params["instance_id"]} in #{params["node_id"]}")
444
+ @provisioner.migrate_instance(params["node_id"], params["instance_id"], params["action"]) do |msg|
445
+ if msg["success"]
446
+ async_reply(msg["response"].to_json)
447
+ else
448
+ async_reply_error(msg["response"])
449
+ end
450
+ end
451
+ async_mode
452
+ end
453
+
454
+ get "/service/internal/v1/migration/:node_id/instances" do
455
+ logger.info("Migration: get instance id list of node #{params["node_id"]}")
456
+ @provisioner.get_instance_id_list(params["node_id"]) do |msg|
457
+ if msg["success"]
458
+ async_reply(msg["response"].to_json)
459
+ else
460
+ async_reply_error(msg["response"])
461
+ end
462
+ end
463
+ async_mode
464
+ end
465
+
466
+ ###################### V2 handlers ########################
467
+
468
+
469
+ #################### Helpers ####################
470
+
471
+ helpers do
472
+
473
+ # Fetches canonical state (handles) from the Cloud Controller
474
+ def fetch_handles(&cb)
475
+ f = Fiber.new do
476
+ @catalog_manager.fetch_handles_from_cc(service[:label], cb)
477
+ end
478
+ f.resume
479
+ end
480
+
481
+ # Update a service handle using REST
482
+ def update_service_handle(handle, &cb)
483
+ f = Fiber.new do
484
+ @catalog_manager.update_handle_in_cc(
485
+ service[:label],
486
+ handle,
487
+ lambda {
488
+ # Update local array in provisioner
489
+ @provisioner.update_handles([handle])
490
+ cb.call(true) if cb
491
+ },
492
+ lambda { cb.call(false) if cb }
493
+ )
494
+ end
495
+ f.resume
496
+ end
497
+
498
+ # Lets the cloud controller know we're alive and where it can find us
499
+ def send_heartbeat
500
+ @catalog_manager.update_catalog(
501
+ true,
502
+ lambda { return get_current_catalog },
503
+ nil
504
+ )
505
+ end
506
+
507
+ # Lets the cloud controller know that we're going away
508
+ def send_deactivation_notice(stop_event_loop=true)
509
+ @catalog_manager.update_catalog(
510
+ false,
511
+ lambda { return get_current_catalog },
512
+ lambda { event_machine.stop if stop_event_loop }
513
+ )
514
+ end
515
+
516
+ def plan_exists?(req)
517
+ return true if req.plan.nil?
518
+
519
+ plan_unique_ids = service.fetch(:plans).values.map { |p| p.fetch(:unique_id) }
520
+ return true if plan_unique_ids.include?(req.unique_id)
521
+
522
+ plan_names = service.fetch(:plans).values.map { |p| p.fetch(:name).to_s }
523
+ return true if plan_names.include?(req.plan.to_s)
524
+
525
+ return false
526
+ end
527
+ end
528
+ end
529
+ end