vcap_services_base 0.2.10

Sign up to get free protection for your applications and to get access to all the features.
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