bosh-director 1.3215.4.0 → 1.3232.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. checksums.yaml +4 -4
  2. data/bin/bosh-director-console +1 -1
  3. data/bin/bosh-director-drain-workers +8 -2
  4. data/bin/bosh-director-worker +34 -53
  5. data/db/migrations/director/20110617211923_add_deployments_release_versions.rb +2 -2
  6. data/db/migrations/director/20120524175805_add_task_type.rb +23 -23
  7. data/db/migrations/director/20130531172604_add_director_attributes.rb +1 -2
  8. data/db/migrations/director/20140116002324_pivot_director_attributes.rb +1 -2
  9. data/db/migrations/director/20160210201838_denormalize_compiled_package_stemcell_id_to_stemcell_name_and_version.rb +7 -9
  10. data/db/migrations/director/20160211174110_add_events.rb +22 -0
  11. data/db/migrations/director/20160324181932_create_delayed_jobs.rb +22 -0
  12. data/db/migrations/director/20160324182211_add_locks.rb +15 -0
  13. data/db/migrations/director/20160329201256_set_instances_with_nil_serial_to_false.rb +15 -0
  14. data/db/migrations/director/20160331225404_backfill_stemcell_os.rb +9 -0
  15. data/db/migrations/director/20160411104407_add_task_started_at.rb +9 -0
  16. data/lib/bosh/director.rb +9 -2
  17. data/lib/bosh/director/agent_client.rb +22 -9
  18. data/lib/bosh/director/api.rb +0 -1
  19. data/lib/bosh/director/api/api_helper.rb +1 -1
  20. data/lib/bosh/director/api/controllers/base_controller.rb +5 -1
  21. data/lib/bosh/director/api/controllers/cloud_configs_controller.rb +18 -2
  22. data/lib/bosh/director/api/controllers/deployments_controller.rb +16 -9
  23. data/lib/bosh/director/api/controllers/events_controller.rb +37 -0
  24. data/lib/bosh/director/api/controllers/locks_controller.rb +7 -11
  25. data/lib/bosh/director/api/controllers/packages_controller.rb +1 -1
  26. data/lib/bosh/director/api/controllers/runtime_configs_controller.rb +18 -2
  27. data/lib/bosh/director/api/controllers/tasks_controller.rb +7 -2
  28. data/lib/bosh/director/api/deployment_lookup.rb +1 -1
  29. data/lib/bosh/director/api/deployment_manager.rb +1 -1
  30. data/lib/bosh/director/api/event_manager.rb +68 -0
  31. data/lib/bosh/director/api/extensions/scoping.rb +2 -2
  32. data/lib/bosh/director/api/extensions/syslog_request_logger.rb +75 -0
  33. data/lib/bosh/director/api/instance_lookup.rb +2 -2
  34. data/lib/bosh/director/api/instance_manager.rb +2 -2
  35. data/lib/bosh/director/api/local_identity_provider.rb +8 -0
  36. data/lib/bosh/director/api/property_manager.rb +6 -5
  37. data/lib/bosh/director/api/release_manager.rb +3 -3
  38. data/lib/bosh/director/api/resource_manager.rb +2 -2
  39. data/lib/bosh/director/api/resurrector_manager.rb +1 -1
  40. data/lib/bosh/director/api/route_configuration.rb +1 -0
  41. data/lib/bosh/director/api/stemcell_manager.rb +5 -5
  42. data/lib/bosh/director/api/task_manager.rb +1 -0
  43. data/lib/bosh/director/api/task_remover.rb +1 -1
  44. data/lib/bosh/director/api/uaa_identity_provider.rb +9 -1
  45. data/lib/bosh/director/api/user/database_user_manager.rb +1 -1
  46. data/lib/bosh/director/app.rb +1 -1
  47. data/lib/bosh/director/arp_flusher.rb +23 -0
  48. data/lib/bosh/director/cloudcheck_helper.rb +4 -3
  49. data/lib/bosh/director/compile_task.rb +6 -6
  50. data/lib/bosh/director/compile_task_generator.rb +6 -6
  51. data/lib/bosh/director/compiled_release_downloader.rb +4 -4
  52. data/lib/bosh/director/config.rb +29 -87
  53. data/lib/bosh/director/deployment_deleter.rb +6 -6
  54. data/lib/bosh/director/deployment_plan/agent_state_migrator.rb +2 -2
  55. data/lib/bosh/director/deployment_plan/assembler.rb +1 -1
  56. data/lib/bosh/director/deployment_plan/compilation_instance_pool.rb +26 -1
  57. data/lib/bosh/director/deployment_plan/deployment_repo.rb +1 -1
  58. data/lib/bosh/director/deployment_plan/disk_type.rb +1 -1
  59. data/lib/bosh/director/deployment_plan/instance.rb +2 -2
  60. data/lib/bosh/director/deployment_plan/instance_plan.rb +2 -2
  61. data/lib/bosh/director/deployment_plan/instance_spec.rb +2 -0
  62. data/lib/bosh/director/deployment_plan/ip_provider/ip_provider.rb +7 -3
  63. data/lib/bosh/director/deployment_plan/job.rb +12 -10
  64. data/lib/bosh/director/deployment_plan/job_spec_parser.rb +4 -4
  65. data/lib/bosh/director/deployment_plan/links/link.rb +1 -0
  66. data/lib/bosh/director/deployment_plan/links/link_path.rb +18 -19
  67. data/lib/bosh/director/deployment_plan/links/links_resolver.rb +2 -0
  68. data/lib/bosh/director/deployment_plan/links/template_link.rb +1 -1
  69. data/lib/bosh/director/deployment_plan/manual_network.rb +1 -1
  70. data/lib/bosh/director/deployment_plan/manual_network_subnet.rb +6 -6
  71. data/lib/bosh/director/deployment_plan/planner.rb +3 -3
  72. data/lib/bosh/director/deployment_plan/planner_factory.rb +38 -40
  73. data/lib/bosh/director/deployment_plan/release_version.rb +5 -5
  74. data/lib/bosh/director/deployment_plan/runtime_manifest_parser.rb +22 -18
  75. data/lib/bosh/director/deployment_plan/steps/package_compile_step.rb +14 -16
  76. data/lib/bosh/director/deployment_plan/steps/update_step.rb +5 -5
  77. data/lib/bosh/director/deployment_plan/template.rb +61 -1
  78. data/lib/bosh/director/deployment_plan/update_config.rb +1 -1
  79. data/lib/bosh/director/disk_manager.rb +49 -40
  80. data/lib/bosh/director/dns/canonicalizer.rb +2 -2
  81. data/lib/bosh/director/dns/dns_manager.rb +2 -2
  82. data/lib/bosh/director/dns/powerdns.rb +2 -2
  83. data/lib/bosh/director/download_helper.rb +5 -5
  84. data/lib/bosh/director/errand/job_manager.rb +5 -6
  85. data/lib/bosh/director/errand/result.rb +1 -1
  86. data/lib/bosh/director/errand/runner.rb +2 -3
  87. data/lib/bosh/director/event_log.rb +1 -7
  88. data/lib/bosh/director/ext.rb +0 -6
  89. data/lib/bosh/director/instance_deleter.rb +23 -2
  90. data/lib/bosh/director/instance_updater.rb +62 -6
  91. data/lib/bosh/director/instance_updater/state_applier.rb +2 -2
  92. data/lib/bosh/director/job_queue.rb +4 -2
  93. data/lib/bosh/director/job_runner.rb +3 -8
  94. data/lib/bosh/director/jobs/backup.rb +1 -1
  95. data/lib/bosh/director/jobs/base_job.rb +10 -6
  96. data/lib/bosh/director/jobs/cleanup_artifacts.rb +6 -6
  97. data/lib/bosh/director/jobs/db_job.rb +87 -0
  98. data/lib/bosh/director/jobs/delete_deployment.rb +23 -2
  99. data/lib/bosh/director/jobs/delete_deployment_snapshots.rb +1 -1
  100. data/lib/bosh/director/jobs/delete_orphan_disks.rb +2 -2
  101. data/lib/bosh/director/jobs/delete_release.rb +2 -2
  102. data/lib/bosh/director/jobs/delete_stemcell.rb +1 -1
  103. data/lib/bosh/director/jobs/export_release.rb +4 -2
  104. data/lib/bosh/director/jobs/fetch_logs.rb +1 -1
  105. data/lib/bosh/director/jobs/helpers/blob_deleter.rb +1 -1
  106. data/lib/bosh/director/jobs/helpers/name_version_release_deleter.rb +3 -3
  107. data/lib/bosh/director/jobs/helpers/release_version_deleter.rb +1 -1
  108. data/lib/bosh/director/jobs/helpers/stemcell_deleter.rb +2 -12
  109. data/lib/bosh/director/jobs/release/release_job.rb +13 -28
  110. data/lib/bosh/director/jobs/run_errand.rb +6 -6
  111. data/lib/bosh/director/jobs/scheduled_backup.rb +1 -1
  112. data/lib/bosh/director/jobs/scheduled_events_cleanup.rb +31 -0
  113. data/lib/bosh/director/jobs/scheduled_orphan_cleanup.rb +1 -1
  114. data/lib/bosh/director/jobs/snapshot_deployment.rb +4 -1
  115. data/lib/bosh/director/jobs/ssh.rb +36 -14
  116. data/lib/bosh/director/jobs/update_deployment.rb +28 -6
  117. data/lib/bosh/director/jobs/update_release.rb +31 -41
  118. data/lib/bosh/director/jobs/update_stemcell.rb +4 -4
  119. data/lib/bosh/director/jobs/vm_state.rb +1 -2
  120. data/lib/bosh/director/lock.rb +30 -55
  121. data/lib/bosh/director/logs_fetcher.rb +2 -3
  122. data/lib/bosh/director/manifest/changeset.rb +88 -42
  123. data/lib/bosh/director/manifest/manifest.rb +1 -1
  124. data/lib/bosh/director/models.rb +3 -0
  125. data/lib/bosh/director/models/event.rb +18 -0
  126. data/lib/bosh/director/models/lock.rb +9 -0
  127. data/lib/bosh/director/models/release_version.rb +3 -1
  128. data/lib/bosh/director/problem_handlers/base.rb +3 -3
  129. data/lib/bosh/director/problem_handlers/inactive_disk.rb +4 -4
  130. data/lib/bosh/director/problem_handlers/missing_disk.rb +3 -3
  131. data/lib/bosh/director/problem_handlers/missing_vm.rb +1 -1
  132. data/lib/bosh/director/problem_handlers/mount_info_mismatch.rb +3 -3
  133. data/lib/bosh/director/problem_handlers/unresponsive_agent.rb +2 -2
  134. data/lib/bosh/director/problem_resolver.rb +5 -5
  135. data/lib/bosh/director/problem_scanner/problem_register.rb +1 -1
  136. data/lib/bosh/director/problem_scanner/scanner.rb +3 -2
  137. data/lib/bosh/director/scheduler.rb +3 -3
  138. data/lib/bosh/director/sequel.rb +1 -3
  139. data/lib/bosh/director/stopper.rb +1 -1
  140. data/lib/bosh/director/validation_helper.rb +60 -37
  141. data/lib/bosh/director/version.rb +1 -1
  142. data/lib/bosh/director/vm_creator.rb +39 -7
  143. data/lib/bosh/director/vm_deleter.rb +29 -2
  144. data/lib/bosh/director/vm_metadata_updater.rb +4 -0
  145. data/lib/bosh/director/worker.rb +52 -0
  146. metadata +47 -61
  147. data/lib/bosh/director/manifest/redactor.rb +0 -44
@@ -100,6 +100,10 @@ module Bosh::Director
100
100
  send_message(:unmount_disk, *args)
101
101
  end
102
102
 
103
+ def delete_arp_entries(*args)
104
+ fire_and_forget(:delete_arp_entries, *args)
105
+ end
106
+
103
107
  def update_settings(certs)
104
108
  begin
105
109
  send_message(:update_settings, {"trusted_certs" => certs})
@@ -166,13 +170,7 @@ module Bosh::Director
166
170
  end
167
171
  end
168
172
 
169
- def handle_method(method_name, args)
170
- result = {}
171
- result.extend(MonitorMixin)
172
-
173
- cond = result.new_cond
174
- timeout_time = Time.now.to_f + @timeout
175
-
173
+ def send_nats_request(method_name, args, &callback)
176
174
  request = { :protocol => PROTOCOL_VERSION, :method => method_name, :arguments => args }
177
175
 
178
176
  if @encryption_handler
@@ -182,8 +180,17 @@ module Bosh::Director
182
180
  end
183
181
 
184
182
  recipient = "#{@service_name}.#{@client_id}"
183
+ @nats_rpc.send_request(recipient, request, &callback)
184
+ end
185
185
 
186
- request_id = @nats_rpc.send_request(recipient, request) do |response|
186
+ def handle_method(method_name, args)
187
+ result = {}
188
+ result.extend(MonitorMixin)
189
+
190
+ cond = result.new_cond
191
+ timeout_time = Time.now.to_f + @timeout
192
+
193
+ request_id = send_nats_request(method_name, args) do |response|
187
194
  if @encryption_handler
188
195
  begin
189
196
  response = @encryption_handler.decrypt(response["encrypted_data"])
@@ -206,7 +213,7 @@ module Bosh::Director
206
213
  unless timeout > 0
207
214
  @nats_rpc.cancel_request(request_id)
208
215
  raise RpcTimeout,
209
- "Timed out sending `#{method_name}' to #{@client_id} " +
216
+ "Timed out sending '#{method_name}' to #{@client_id} " +
210
217
  "after #{@timeout} seconds"
211
218
  end
212
219
  cond.wait(timeout)
@@ -279,6 +286,12 @@ module Bosh::Director
279
286
  end
280
287
  end
281
288
 
289
+ def fire_and_forget(message_name, *args)
290
+ send_nats_request(message_name, args)
291
+ rescue => e
292
+ @logger.warn("Ignoring '#{e.message}' error from the agent: #{e.inspect}. Received while trying to run: #{message_name} on client: '#{@client_id}'")
293
+ end
294
+
282
295
  def send_message(method_name, *args, &blk)
283
296
  task = start_task(method_name, *args)
284
297
  if task['agent_task_id']
@@ -10,7 +10,6 @@ require 'bosh/director/api/http_constants'
10
10
  require 'bosh/director/api/api_helper'
11
11
  require 'bosh/director/api/task_helper'
12
12
 
13
- require 'bosh/director/api/backup_manager'
14
13
  require 'bosh/director/api/deployment_manager'
15
14
  require 'bosh/director/api/instance_manager'
16
15
  require 'bosh/director/api/problem_manager'
@@ -99,7 +99,7 @@ module Bosh::Director
99
99
 
100
100
  begin
101
101
  Psych.parse(yml_string)
102
- rescue Psych::SyntaxError => e
102
+ rescue Exception => e
103
103
  raise BadManifest, "Incorrect YAML structure of the uploaded manifest: #{e.inspect}"
104
104
  end
105
105
  end
@@ -20,9 +20,13 @@ module Bosh::Director
20
20
  @task_manager = TaskManager.new
21
21
  @dns_manager = DnsManagerProvider.create
22
22
  @disk_manager = DiskManager.new(nil, @logger)
23
+ @event_manager = EventManager.new(config.record_events)
23
24
  end
24
25
 
25
- register Bosh::Director::Api::Extensions::Scoping
26
+ register(Bosh::Director::Api::Extensions::SyslogRequestLogger)
27
+ log_request_to_syslog
28
+
29
+ register(Bosh::Director::Api::Extensions::Scoping)
26
30
 
27
31
  mime_type :tgz, 'application/x-compressed'
28
32
  mime_type :multipart, 'multipart/form-data'
@@ -5,9 +5,15 @@ module Bosh::Director
5
5
  class CloudConfigsController < BaseController
6
6
  post '/', :consumes => :yaml do
7
7
  manifest_text = request.body.read
8
- validate_manifest_yml(manifest_text)
8
+ begin
9
+ validate_manifest_yml(manifest_text)
10
+ Bosh::Director::Api::CloudConfigManager.new.update(manifest_text)
11
+ create_event
12
+ rescue => e
13
+ create_event e
14
+ raise e
15
+ end
9
16
 
10
- Bosh::Director::Api::CloudConfigManager.new.update(manifest_text)
11
17
  status(201)
12
18
  end
13
19
 
@@ -36,6 +42,16 @@ module Bosh::Director
36
42
  end
37
43
  )
38
44
  end
45
+
46
+ private
47
+ def create_event(error = nil)
48
+ @event_manager.create_event({
49
+ user: current_user,
50
+ action: "update",
51
+ object_type: "cloud-config",
52
+ error: error
53
+ })
54
+ end
39
55
  end
40
56
  end
41
57
  end
@@ -371,15 +371,22 @@ module Bosh::Director
371
371
 
372
372
  redact = params['redact'] != 'false'
373
373
 
374
- diff = before_manifest.diff(after_manifest, redact)
374
+ result = {
375
+ 'context' => {
376
+ 'cloud_config_id' => after_cloud_config ? after_cloud_config.id : nil,
377
+ 'runtime_config_id' => after_runtime_config ? after_runtime_config.id : nil
378
+ }
379
+ }
380
+
381
+ begin
382
+ diff = before_manifest.diff(after_manifest, redact)
383
+ result['diff'] = diff.map { |l| [l.to_s, l.status] }
384
+ rescue => error
385
+ result['diff'] = []
386
+ result['error'] = "Unable to diff manifest: #{error.inspect}\n#{error.backtrace.join("\n")}"
387
+ end
375
388
 
376
- json_encode({
377
- 'context' => {
378
- 'cloud_config_id' => after_cloud_config ? after_cloud_config.id : nil,
379
- 'runtime_config_id' => after_runtime_config ? after_runtime_config.id : nil
380
- },
381
- 'diff' => diff.map { |l| [l.to_s, l.status] }
382
- })
389
+ json_encode(result)
383
390
  end
384
391
 
385
392
  post '/:deployment/errands/:errand_name/runs' do
@@ -436,7 +443,7 @@ module Bosh::Director
436
443
  Integer(str)
437
444
  rescue ArgumentError
438
445
  if str !~ /^[A-Fa-f0-9]{8}-[A-Fa-f0-9-]{27}$/
439
- raise InstanceInvalidIndex, "Invalid instance index or id `#{str}'"
446
+ raise InstanceInvalidIndex, "Invalid instance index or id '#{str}'"
440
447
  end
441
448
  end
442
449
  end
@@ -0,0 +1,37 @@
1
+ require 'bosh/director/api/controllers/base_controller'
2
+
3
+ module Bosh::Director
4
+ module Api::Controllers
5
+ class EventsController < BaseController
6
+ EVENT_LIMIT = 200
7
+
8
+ get '/' do
9
+ content_type(:json)
10
+
11
+ events = Models::Event.order_by(Sequel.desc(:id))
12
+
13
+ if params['before_id']
14
+ before_id = params['before_id'].to_i
15
+ events = events.filter("id < ?", before_id)
16
+ end
17
+
18
+ if params['task']
19
+ events = events.where(task: params['task'])
20
+ end
21
+
22
+ if params['deployment']
23
+ events = events.where(deployment: params['deployment'])
24
+ end
25
+
26
+ if params['instance']
27
+ events = events.where(instance: params['instance'])
28
+ end
29
+
30
+ events = events.limit(EVENT_LIMIT).map do |event|
31
+ @event_manager.event_to_hash(event)
32
+ end
33
+ json_encode(events)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -2,19 +2,15 @@ module Bosh::Director
2
2
  module Api::Controllers
3
3
  class LocksController < BaseController
4
4
  get '/', scope: :read do
5
- redis = Config.redis
5
+ wait_until = Time.now - 6 * 10.seconds # 6 * lock_renewal_interval
6
+ Models::Lock.where{expired_at <= wait_until}.destroy
6
7
 
7
8
  locks = []
8
- lock_keys = redis.keys('lock:*')
9
- # Deliberately not using redis futures here as we expect that the number of lock keys will be very small
10
- lock_keys.each do |lock_key|
11
- lock_value = redis.get(lock_key)
12
- unless lock_value.nil?
13
- lock_type = lock_key.split(':')[1]
14
- lock_resource = lock_key.split(':')[2..-1]
15
- lock_timeout = lock_value.split(':')[0]
16
- locks << { type: lock_type, resource: lock_resource, timeout: lock_timeout }
17
- end
9
+ Models::Lock.all.each do |lock_record|
10
+ lock_type = lock_record.name.split(':')[1]
11
+ lock_resource = lock_record.name.split(':')[2..-1]
12
+ lock_timeout = lock_record.expired_at.strftime('%s.%6N')
13
+ locks << { type: lock_type, resource: lock_resource, timeout: lock_timeout }
18
14
  end
19
15
 
20
16
  content_type(:json)
@@ -16,7 +16,7 @@ module Bosh::Director
16
16
  fingerprint_list << package['fingerprint'] if package['fingerprint']
17
17
  end
18
18
 
19
- matching_packages = Models::Package.where(fingerprint: fingerprint_list, ~:sha1 => nil, ~:blobstore_id => nil).all
19
+ matching_packages = Models::Package.where(Sequel.~(:sha1 => nil), Sequel.~(:blobstore_id => nil), fingerprint: fingerprint_list).all
20
20
 
21
21
  json_encode(matching_packages.map(&:fingerprint).compact.uniq)
22
22
  end
@@ -5,9 +5,15 @@ module Bosh::Director
5
5
  class RuntimeConfigsController < BaseController
6
6
  post '/', :consumes => :yaml do
7
7
  manifest_text = request.body.read
8
- validate_manifest_yml(manifest_text)
8
+ begin
9
+ validate_manifest_yml(manifest_text)
10
+ Bosh::Director::Api::RuntimeConfigManager.new.update(manifest_text)
11
+ create_event
12
+ rescue => e
13
+ create_event e
14
+ raise e
15
+ end
9
16
 
10
- Bosh::Director::Api::RuntimeConfigManager.new.update(manifest_text)
11
17
  status(201)
12
18
  end
13
19
 
@@ -36,6 +42,16 @@ module Bosh::Director
36
42
  end
37
43
  )
38
44
  end
45
+
46
+ private
47
+ def create_event(error = nil)
48
+ @event_manager.create_event({
49
+ user: current_user,
50
+ action: "update",
51
+ object_type: "runtime-config",
52
+ error: error
53
+ })
54
+ end
39
55
  end
40
56
  end
41
57
  end
@@ -17,7 +17,7 @@ module Bosh::Director
17
17
  task = @task_manager.find_task(params[:id])
18
18
  if type == 'debug' || type == 'cpi' || !type
19
19
  check_access_to_task(task, :admin)
20
- elsif type == 'event' || type == 'result'
20
+ elsif type == 'event' || type == 'result' || type == 'none'
21
21
  check_access_to_task(task, :read)
22
22
  else
23
23
  raise UnauthorizedToAccessDeployment, "Unknown type #{type}"
@@ -63,7 +63,7 @@ module Bosh::Director
63
63
  @permission_authorizer.granted_or_raise(deployment, :read, token_scopes)
64
64
  end
65
65
 
66
- tasks = dataset.order_by(:timestamp.desc).map
66
+ tasks = dataset.order_by(Sequel.desc(:timestamp)).map
67
67
 
68
68
  unless @permission_authorizer.is_granted?(:director, :read, token_scopes)
69
69
  permitted_deployments = @deployment_manager.all_by_name_asc.select { |deployment|
@@ -112,6 +112,11 @@ module Bosh::Director
112
112
  # at /var/vcap/store/director/tasks/5/event
113
113
  get '/:id/output', authorization: :task_output, scope: :authorization do
114
114
  log_type = params[:type] || 'debug'
115
+
116
+ if log_type == "none"
117
+ halt(204)
118
+ end
119
+
115
120
  task = @task_manager.find_task(params[:id])
116
121
 
117
122
  if task.output.nil?
@@ -4,7 +4,7 @@ module Bosh::Director
4
4
  def by_name(name)
5
5
  deployment = Models::Deployment[name: name]
6
6
  if deployment.nil?
7
- raise DeploymentNotFound, "Deployment `#{name}' doesn't exist"
7
+ raise DeploymentNotFound, "Deployment '#{name}' doesn't exist"
8
8
  end
9
9
  deployment
10
10
  end
@@ -12,7 +12,7 @@ module Bosh::Director
12
12
  end
13
13
 
14
14
  def all_by_name_asc
15
- Bosh::Director::Models::Deployment.order_by(:name.asc).all
15
+ Bosh::Director::Models::Deployment.order_by(Sequel.asc(:name)).all
16
16
  end
17
17
 
18
18
  def create_deployment(username, deployment_manifest_file_path, cloud_config, runtime_config, deployment_name, options = {})
@@ -0,0 +1,68 @@
1
+ module Bosh::Director
2
+ module Api
3
+ class EventManager
4
+ def initialize(record_events)
5
+ @record_events = record_events
6
+ end
7
+
8
+ def event_to_hash(event)
9
+ {
10
+ 'id' => event.id.to_s,
11
+ 'parent_id' => event.parent_id.to_s,
12
+ 'timestamp' => event.timestamp.to_i,
13
+ 'user' => event.user,
14
+ 'action' => event.action,
15
+ 'object_type' => event.object_type,
16
+ 'object_name' => event.object_name,
17
+ 'error' => event.error,
18
+ 'task' => event.task,
19
+ 'deployment' => event.deployment,
20
+ 'instance' => event.instance,
21
+ 'context' => event.context
22
+ }.reject { |k, v| v.nil? || v == '' }
23
+ end
24
+
25
+ def create_event(options)
26
+ unless @record_events
27
+ return Models::Event.new
28
+ end
29
+
30
+ parent_id = options.fetch(:parent_id, nil)
31
+ user = options[:user]
32
+ action = options[:action]
33
+ object_type = options[:object_type]
34
+ object_name = options.fetch(:object_name, nil)
35
+ task = options.fetch(:task, nil)
36
+ error = options.fetch(:error){ |error| error ? error.to_s: nil }
37
+ deployment = options.fetch(:deployment, nil)
38
+ instance = options.fetch(:instance, nil)
39
+ context = options.fetch(:context, {})
40
+
41
+ Models::Event.create(
42
+ parent_id: parent_id,
43
+ timestamp: Time.now,
44
+ user: user,
45
+ action: action,
46
+ object_type: object_type,
47
+ object_name: object_name,
48
+ error: error,
49
+ task: task,
50
+ deployment: deployment,
51
+ instance: instance,
52
+ context: context)
53
+ end
54
+
55
+ def remove_old_events (max_events = 10000)
56
+ if Bosh::Director::Models::Event.count > max_events
57
+ last_id = Bosh::Director::Models::Event.
58
+ order { Sequel.desc(:id) }.limit(1, max_events).first.id
59
+ last_parent_id = Bosh::Director::Models::Event.
60
+ order { Sequel.desc(:id) }.limit(max_events).min(:parent_id)
61
+ start_id_to_remove = (last_parent_id.nil? || (last_parent_id > last_id)) ? last_id+1: last_parent_id
62
+
63
+ Bosh::Director::Models::Event.filter("id < ?", start_id_to_remove).delete if start_id_to_remove != 0
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -4,8 +4,8 @@ module Bosh::Director
4
4
  module Scoping
5
5
  module Helpers
6
6
  def current_user
7
- @user.username if @user
8
- end
7
+ @user.username_or_client if @user
8
+ end
9
9
 
10
10
  def token_scopes
11
11
  @user.scopes if @user
@@ -0,0 +1,75 @@
1
+ #feature not supported for ruby < 2.0.0
2
+ begin
3
+ require 'syslog/logger'
4
+ rescue LoadError
5
+ puts "Failed to load Syslog::Logger. Ruby version #{RUBY_VERSION} not supported. Use RUBY_VERSION >= 2.0.0"
6
+ end
7
+
8
+ require 'socket'
9
+
10
+ module Bosh::Director
11
+ module Api
12
+ module Extensions
13
+ module SyslogRequestLogger
14
+
15
+ DESIRED_HEADERS = %w(
16
+ HTTP_HOST
17
+ HTTP_X_REAL_IP
18
+ HTTP_X_FORWARDED_FOR
19
+ HTTP_X_FORWARDED_PROTO
20
+ HTTP_USER_AGENT
21
+ HTTP_X_BOSH_UPLOAD_REQUEST_TIME
22
+ )
23
+
24
+ def log_request_to_syslog
25
+ after do
26
+ if @config.log_access_events_to_syslog && RUBY_VERSION.to_i > 1
27
+ header_string = ''
28
+ filtered_headers = request.env.select { |key, _| DESIRED_HEADERS.include?(key) }
29
+ .collect { |key, value| [key.sub(/^HTTP_/, ''), value] }
30
+ filtered_headers.each do |header_set|
31
+ header_string += header_set[0] + "\=" + header_set[1] + "&"
32
+ end
33
+ header_string = header_string[0..-2] if !header_string.empty?
34
+
35
+ filtered_ip_list = Socket.ip_address_list
36
+ .reject { |addr| !addr.ip? || addr.ipv4_loopback? || addr.ipv6_loopback? }
37
+ .map { |addr| addr.ip_address }
38
+
39
+ cef_version = 0
40
+ device_vendor = 'CloudFoundry'
41
+ device_product = 'BOSH'
42
+ device_version = Bosh::Director::VERSION
43
+ signature_id = 'director_api'
44
+ name = "#{request.path}"
45
+ severity = response.status >= 400 ? 7 : 1
46
+
47
+ extension = ''
48
+ if @user
49
+ extension += "duser=#{@user.username} " if @user.username
50
+ extension += "requestClientApplication=#{@user.client} " if @user.client
51
+ end
52
+
53
+ extension += "requestMethod=#{request.request_method} src=#{request.ip} spt=#{@config.port}" +
54
+ " shost=#{Socket.gethostname}" +
55
+ " cs1=#{filtered_ip_list.join(',')} cs1Label=ips" +
56
+ " cs2=#{header_string} cs2Label=httpHeaders" +
57
+ " cs3=#{current_user.nil? ? 'none' : identity_provider.client_info['type']} cs3Label=authType" +
58
+ " cs4=#{response.status} cs4Label=responseStatus"
59
+ if response.status >= 400
60
+ extension += " cs5=#{response.body.join('')[0...500].strip} cs5Label=statusReason"
61
+ end
62
+
63
+ cef_log = 'CEF:%i|%s|%s|%s|%s|%s|%s|%s' % [cef_version, device_vendor, device_product,
64
+ device_version, signature_id, name, severity, extension]
65
+ cef_log_encoded = cef_log.force_encoding(Encoding::UTF_8)
66
+
67
+ Syslog::Logger.new('vcap.bosh.director').info(cef_log_encoded)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+