bosh-director 1.5.0.pre.1113

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 (180) hide show
  1. data/CHANGELOG +34 -0
  2. data/bin/bosh-director +36 -0
  3. data/bin/bosh-director-console +84 -0
  4. data/bin/bosh-director-drain-workers +42 -0
  5. data/bin/bosh-director-migrate +58 -0
  6. data/bin/bosh-director-scheduler +27 -0
  7. data/bin/bosh-director-worker +76 -0
  8. data/db/migrations/README +1 -0
  9. data/db/migrations/director/20110209010747_initial.rb +118 -0
  10. data/db/migrations/director/20110406055800_add_task_user.rb +9 -0
  11. data/db/migrations/director/20110518225809_remove_cid_constrain.rb +13 -0
  12. data/db/migrations/director/20110617211923_add_deployments_release_versions.rb +32 -0
  13. data/db/migrations/director/20110622212607_add_task_checkpoint_timestamp.rb +9 -0
  14. data/db/migrations/director/20110628023039_add_state_to_instances.rb +21 -0
  15. data/db/migrations/director/20110709012332_add_disk_size_to_instances.rb +9 -0
  16. data/db/migrations/director/20110906183441_add_log_bundles.rb +11 -0
  17. data/db/migrations/director/20110907194830_add_logs_json_to_templates.rb +9 -0
  18. data/db/migrations/director/20110915205610_add_persistent_disks.rb +51 -0
  19. data/db/migrations/director/20111005180929_add_properties.rb +14 -0
  20. data/db/migrations/director/20111110024617_add_deployment_problems.rb +24 -0
  21. data/db/migrations/director/20111216214145_recreate_support_for_vms.rb +9 -0
  22. data/db/migrations/director/20120102084027_add_credentials_to_vms.rb +7 -0
  23. data/db/migrations/director/20120427235217_allow_multiple_releases_per_deployment.rb +36 -0
  24. data/db/migrations/director/20120524175805_add_task_type.rb +44 -0
  25. data/db/migrations/director/20120614001930_delete_redundant_deployment_release_relation.rb +34 -0
  26. data/db/migrations/director/20120822004528_add_fingerprint_to_templates_and_packages.rb +17 -0
  27. data/db/migrations/director/20120830191244_add_properties_to_templates.rb +9 -0
  28. data/db/migrations/director/20121106190739_persist_vm_env.rb +9 -0
  29. data/db/migrations/director/20130222232131_add_sha1_to_stemcells.rb +9 -0
  30. data/db/migrations/director/20130312211407_add_commit_hash_to_release_versions.rb +19 -0
  31. data/db/migrations/director/20130409235338_snapshot.rb +15 -0
  32. data/db/migrations/director/20130530164918_add_paused_flag_to_instance.rb +14 -0
  33. data/db/migrations/director/20130531172604_add_director_attributes.rb +13 -0
  34. data/db/migrations/dns/20120123234908_initial.rb +27 -0
  35. data/lib/bosh/director.rb +133 -0
  36. data/lib/bosh/director/agent_client.rb +78 -0
  37. data/lib/bosh/director/api.rb +29 -0
  38. data/lib/bosh/director/api/api_helper.rb +81 -0
  39. data/lib/bosh/director/api/backup_manager.rb +15 -0
  40. data/lib/bosh/director/api/controller.rb +639 -0
  41. data/lib/bosh/director/api/controller_helpers.rb +34 -0
  42. data/lib/bosh/director/api/deployment_lookup.rb +13 -0
  43. data/lib/bosh/director/api/deployment_manager.rb +60 -0
  44. data/lib/bosh/director/api/http_constants.rb +16 -0
  45. data/lib/bosh/director/api/instance_lookup.rb +44 -0
  46. data/lib/bosh/director/api/instance_manager.rb +63 -0
  47. data/lib/bosh/director/api/problem_manager.rb +40 -0
  48. data/lib/bosh/director/api/property_manager.rb +69 -0
  49. data/lib/bosh/director/api/release_manager.rb +59 -0
  50. data/lib/bosh/director/api/resource_manager.rb +69 -0
  51. data/lib/bosh/director/api/resurrector_manager.rb +15 -0
  52. data/lib/bosh/director/api/snapshot_manager.rb +94 -0
  53. data/lib/bosh/director/api/stemcell_manager.rb +50 -0
  54. data/lib/bosh/director/api/task_helper.rb +46 -0
  55. data/lib/bosh/director/api/task_manager.rb +64 -0
  56. data/lib/bosh/director/api/user_manager.rb +72 -0
  57. data/lib/bosh/director/api/vm_state_manager.rb +11 -0
  58. data/lib/bosh/director/app.rb +35 -0
  59. data/lib/bosh/director/blob_util.rb +87 -0
  60. data/lib/bosh/director/blobstores.rb +29 -0
  61. data/lib/bosh/director/client.rb +156 -0
  62. data/lib/bosh/director/cloudcheck_helper.rb +204 -0
  63. data/lib/bosh/director/compile_task.rb +157 -0
  64. data/lib/bosh/director/config.rb +370 -0
  65. data/lib/bosh/director/configuration_hasher.rb +114 -0
  66. data/lib/bosh/director/cycle_helper.rb +36 -0
  67. data/lib/bosh/director/db_backup.rb +22 -0
  68. data/lib/bosh/director/db_backup/adapter.rb +3 -0
  69. data/lib/bosh/director/db_backup/adapter/mysql2.rb +27 -0
  70. data/lib/bosh/director/db_backup/adapter/postgres.rb +36 -0
  71. data/lib/bosh/director/db_backup/adapter/sqlite.rb +17 -0
  72. data/lib/bosh/director/db_backup/error.rb +10 -0
  73. data/lib/bosh/director/deployment_plan.rb +26 -0
  74. data/lib/bosh/director/deployment_plan/assembler.rb +430 -0
  75. data/lib/bosh/director/deployment_plan/compilation_config.rb +54 -0
  76. data/lib/bosh/director/deployment_plan/compiled_package.rb +35 -0
  77. data/lib/bosh/director/deployment_plan/dynamic_network.rb +91 -0
  78. data/lib/bosh/director/deployment_plan/idle_vm.rb +109 -0
  79. data/lib/bosh/director/deployment_plan/instance.rb +413 -0
  80. data/lib/bosh/director/deployment_plan/job.rb +470 -0
  81. data/lib/bosh/director/deployment_plan/manual_network.rb +137 -0
  82. data/lib/bosh/director/deployment_plan/network.rb +74 -0
  83. data/lib/bosh/director/deployment_plan/network_subnet.rb +167 -0
  84. data/lib/bosh/director/deployment_plan/planner.rb +288 -0
  85. data/lib/bosh/director/deployment_plan/preparer.rb +52 -0
  86. data/lib/bosh/director/deployment_plan/release.rb +126 -0
  87. data/lib/bosh/director/deployment_plan/resource_pool.rb +143 -0
  88. data/lib/bosh/director/deployment_plan/resource_pools.rb +68 -0
  89. data/lib/bosh/director/deployment_plan/stemcell.rb +56 -0
  90. data/lib/bosh/director/deployment_plan/template.rb +94 -0
  91. data/lib/bosh/director/deployment_plan/update_config.rb +80 -0
  92. data/lib/bosh/director/deployment_plan/updater.rb +55 -0
  93. data/lib/bosh/director/deployment_plan/vip_network.rb +79 -0
  94. data/lib/bosh/director/dns_helper.rb +204 -0
  95. data/lib/bosh/director/download_helper.rb +44 -0
  96. data/lib/bosh/director/duration.rb +36 -0
  97. data/lib/bosh/director/encryption_helper.rb +10 -0
  98. data/lib/bosh/director/errors.rb +198 -0
  99. data/lib/bosh/director/event_log.rb +136 -0
  100. data/lib/bosh/director/ext.rb +64 -0
  101. data/lib/bosh/director/hash_string_vals.rb +13 -0
  102. data/lib/bosh/director/instance_deleter.rb +109 -0
  103. data/lib/bosh/director/instance_updater.rb +506 -0
  104. data/lib/bosh/director/ip_util.rb +67 -0
  105. data/lib/bosh/director/job_queue.rb +16 -0
  106. data/lib/bosh/director/job_runner.rb +162 -0
  107. data/lib/bosh/director/job_updater.rb +121 -0
  108. data/lib/bosh/director/jobs/backup.rb +86 -0
  109. data/lib/bosh/director/jobs/base_job.rb +66 -0
  110. data/lib/bosh/director/jobs/cloud_check/apply_resolutions.rb +46 -0
  111. data/lib/bosh/director/jobs/cloud_check/scan.rb +38 -0
  112. data/lib/bosh/director/jobs/cloud_check/scan_and_fix.rb +73 -0
  113. data/lib/bosh/director/jobs/create_snapshot.rb +23 -0
  114. data/lib/bosh/director/jobs/delete_deployment.rb +183 -0
  115. data/lib/bosh/director/jobs/delete_deployment_snapshots.rb +34 -0
  116. data/lib/bosh/director/jobs/delete_release.rb +219 -0
  117. data/lib/bosh/director/jobs/delete_snapshots.rb +23 -0
  118. data/lib/bosh/director/jobs/delete_stemcell.rb +102 -0
  119. data/lib/bosh/director/jobs/fetch_logs.rb +99 -0
  120. data/lib/bosh/director/jobs/scheduled_backup.rb +38 -0
  121. data/lib/bosh/director/jobs/snapshot_deployment.rb +61 -0
  122. data/lib/bosh/director/jobs/snapshot_deployments.rb +23 -0
  123. data/lib/bosh/director/jobs/snapshot_self.rb +43 -0
  124. data/lib/bosh/director/jobs/ssh.rb +59 -0
  125. data/lib/bosh/director/jobs/update_deployment.rb +110 -0
  126. data/lib/bosh/director/jobs/update_release.rb +672 -0
  127. data/lib/bosh/director/jobs/update_stemcell.rb +109 -0
  128. data/lib/bosh/director/jobs/vm_state.rb +89 -0
  129. data/lib/bosh/director/lock.rb +133 -0
  130. data/lib/bosh/director/lock_helper.rb +92 -0
  131. data/lib/bosh/director/models.rb +29 -0
  132. data/lib/bosh/director/models/compiled_package.rb +33 -0
  133. data/lib/bosh/director/models/deployment.rb +22 -0
  134. data/lib/bosh/director/models/deployment_problem.rb +49 -0
  135. data/lib/bosh/director/models/deployment_property.rb +21 -0
  136. data/lib/bosh/director/models/director_attribute.rb +9 -0
  137. data/lib/bosh/director/models/dns.rb +9 -0
  138. data/lib/bosh/director/models/dns/domain.rb +9 -0
  139. data/lib/bosh/director/models/dns/record.rb +7 -0
  140. data/lib/bosh/director/models/helpers/model_helper.rb +7 -0
  141. data/lib/bosh/director/models/instance.rb +28 -0
  142. data/lib/bosh/director/models/log_bundle.rb +10 -0
  143. data/lib/bosh/director/models/package.rb +30 -0
  144. data/lib/bosh/director/models/persistent_disk.rb +13 -0
  145. data/lib/bosh/director/models/release.rb +17 -0
  146. data/lib/bosh/director/models/release_version.rb +16 -0
  147. data/lib/bosh/director/models/snapshot.rb +13 -0
  148. data/lib/bosh/director/models/stemcell.rb +18 -0
  149. data/lib/bosh/director/models/task.rb +10 -0
  150. data/lib/bosh/director/models/template.rb +44 -0
  151. data/lib/bosh/director/models/user.rb +11 -0
  152. data/lib/bosh/director/models/vm.rb +42 -0
  153. data/lib/bosh/director/nats_rpc.rb +54 -0
  154. data/lib/bosh/director/network_reservation.rb +121 -0
  155. data/lib/bosh/director/next_rebase_version.rb +20 -0
  156. data/lib/bosh/director/package_compiler.rb +423 -0
  157. data/lib/bosh/director/problem_handlers/base.rb +153 -0
  158. data/lib/bosh/director/problem_handlers/inactive_disk.rb +112 -0
  159. data/lib/bosh/director/problem_handlers/invalid_problem.rb +28 -0
  160. data/lib/bosh/director/problem_handlers/missing_vm.rb +34 -0
  161. data/lib/bosh/director/problem_handlers/mount_info_mismatch.rb +62 -0
  162. data/lib/bosh/director/problem_handlers/out_of_sync_vm.rb +64 -0
  163. data/lib/bosh/director/problem_handlers/unbound_instance_vm.rb +85 -0
  164. data/lib/bosh/director/problem_handlers/unresponsive_agent.rb +78 -0
  165. data/lib/bosh/director/problem_resolver.rb +103 -0
  166. data/lib/bosh/director/problem_scanner.rb +268 -0
  167. data/lib/bosh/director/resource_pool_updater.rb +216 -0
  168. data/lib/bosh/director/scheduler.rb +57 -0
  169. data/lib/bosh/director/sequel.rb +13 -0
  170. data/lib/bosh/director/tar_gzipper.rb +47 -0
  171. data/lib/bosh/director/task_result_file.rb +19 -0
  172. data/lib/bosh/director/thread_pool.rb +8 -0
  173. data/lib/bosh/director/validation_helper.rb +55 -0
  174. data/lib/bosh/director/version.rb +7 -0
  175. data/lib/bosh/director/vm_creator.rb +80 -0
  176. data/lib/bosh/director/vm_data.rb +63 -0
  177. data/lib/bosh/director/vm_metadata_updater.rb +29 -0
  178. data/lib/bosh/director/vm_reuser.rb +63 -0
  179. data/lib/cloud/dummy.rb +149 -0
  180. metadata +664 -0
@@ -0,0 +1,370 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ require 'fileutils'
4
+
5
+ module Bosh::Director
6
+
7
+ # We are in the slow painful process of extracting all of this class-level
8
+ # behavior into instance behavior, much of it on the App class. When this
9
+ # process is complete, the Config will be responsible only for maintaining
10
+ # configuration information - not holding the state of the world.
11
+
12
+ class Config
13
+ class << self
14
+ include DnsHelper
15
+
16
+ CONFIG_OPTIONS = [
17
+ :base_dir,
18
+ :cloud_options,
19
+ :db,
20
+ :dns,
21
+ :dns_db,
22
+ :dns_domain_name,
23
+ :event_log,
24
+ :logger,
25
+ :max_tasks,
26
+ :max_threads,
27
+ :name,
28
+ :process_uuid,
29
+ :result,
30
+ :revision,
31
+ :task_checkpoint_interval,
32
+ :uuid,
33
+ :current_job,
34
+ :encryption,
35
+ :fix_stateful_nodes,
36
+ :enable_snapshots
37
+ ]
38
+
39
+ CONFIG_OPTIONS.each do |option|
40
+ attr_accessor option
41
+ end
42
+
43
+ attr_reader :db_config
44
+
45
+ def clear
46
+ CONFIG_OPTIONS.each do |option|
47
+ self.instance_variable_set("@#{option}".to_sym, nil)
48
+ end
49
+
50
+ Thread.list.each do |thr|
51
+ thr[:bosh] = nil
52
+ end
53
+
54
+ @blobstore = nil
55
+ @compiled_package_cache = nil
56
+ @nats = nil
57
+ @nats_rpc = nil
58
+ @cloud = nil
59
+ end
60
+
61
+ def configure(config)
62
+
63
+ @base_dir = config["dir"]
64
+ FileUtils.mkdir_p(@base_dir)
65
+
66
+ # checkpoint task progress every 30 secs
67
+ @task_checkpoint_interval = 30
68
+
69
+ logging = config.fetch('logging', {})
70
+ @log_device = Logger::LogDevice.new(logging.fetch('file', STDOUT))
71
+ @logger = Logger.new(@log_device)
72
+ @logger.level = Logger.const_get(logging.fetch('level', 'debug').upcase)
73
+ @logger.formatter = ThreadFormatter.new
74
+
75
+ # use a separate logger for redis to make it stfu
76
+ redis_logger = Logger.new(@log_device)
77
+ logging = config.fetch('redis', {}).fetch('logging', {})
78
+ redis_logger_level = logging.fetch('level', 'info').upcase
79
+ redis_logger.level = Logger.const_get(redis_logger_level)
80
+
81
+ # Event logger supposed to be overridden per task,
82
+ # the default one does nothing
83
+ @event_log = EventLog.new
84
+
85
+ # by default keep only last 500 tasks in disk
86
+ @max_tasks = config.fetch("max_tasks", 500).to_i
87
+
88
+ @max_threads = config.fetch("max_threads", 32).to_i
89
+
90
+ self.redis_options= {
91
+ :host => config["redis"]["host"],
92
+ :port => config["redis"]["port"],
93
+ :password => config["redis"]["password"],
94
+ :logger => redis_logger
95
+ }
96
+
97
+ @revision = get_revision
98
+
99
+ @logger.info("Starting BOSH Director: #{VERSION} (#{@revision})")
100
+
101
+ @process_uuid = SecureRandom.uuid
102
+ @nats_uri = config["mbus"]
103
+
104
+ @cloud_options = config["cloud"]
105
+ @compiled_package_cache_options = config["compiled_package_cache"]
106
+ @name = config["name"] || ""
107
+
108
+ @compiled_package_cache = nil
109
+
110
+ @db_config = config['db']
111
+ @db = configure_db(config["db"])
112
+ @dns = config["dns"]
113
+ @dns_domain_name = "bosh"
114
+ if @dns
115
+ @dns_db = configure_db(@dns["db"]) if @dns["db"]
116
+ @dns_domain_name = canonical(@dns["domain_name"]) if @dns["domain_name"]
117
+ end
118
+
119
+ @uuid = override_uuid || retrieve_uuid
120
+ @logger.info("Director UUID: #{@uuid}")
121
+
122
+ @encryption = config["encryption"]
123
+ @fix_stateful_nodes = config.fetch("scan_and_fix", {})
124
+ .fetch("auto_fix_stateful_nodes", false)
125
+ @enable_snapshots = config.fetch('snapshots', {}).fetch('enabled', false)
126
+
127
+ Bosh::Clouds::Config.configure(self)
128
+
129
+ @lock = Monitor.new
130
+ end
131
+
132
+ def log_dir
133
+ File.dirname(@log_device.filename) if @log_device.filename
134
+ end
135
+
136
+ def use_compiled_package_cache?
137
+ !@compiled_package_cache_options.nil?
138
+ end
139
+
140
+ def get_revision
141
+ Dir.chdir(File.expand_path("../../../../../..", __FILE__))
142
+ revision_command = "(cat REVISION 2> /dev/null || " +
143
+ "git show-ref --head --hash=8 2> /dev/null || " +
144
+ "echo 00000000) | head -n1"
145
+ `#{revision_command}`.strip
146
+ end
147
+
148
+ def configure_db(db_config)
149
+ patch_sqlite if db_config["adapter"] == "sqlite"
150
+
151
+ connection_options = db_config.delete('connection_options') {{}}
152
+ db_config.delete_if { |_, v| v.to_s.empty? }
153
+ db_config = db_config.merge(connection_options)
154
+
155
+ db = Sequel.connect(db_config)
156
+ if logger
157
+ db.logger = logger
158
+ db.sql_log_level = :debug
159
+ end
160
+
161
+ db
162
+ end
163
+
164
+ def compiled_package_cache_blobstore
165
+ @lock.synchronize do
166
+ if @compiled_package_cache_blobstore.nil? && use_compiled_package_cache?
167
+ provider = @compiled_package_cache_options["provider"]
168
+ options = @compiled_package_cache_options["options"]
169
+ @compiled_package_cache_blobstore = Bosh::Blobstore::Client.create(provider, options)
170
+ end
171
+ end
172
+ @compiled_package_cache_blobstore
173
+ end
174
+
175
+ def compiled_package_cache_provider
176
+ use_compiled_package_cache? ? @compiled_package_cache_options["provider"] : nil
177
+ end
178
+
179
+ def cloud_type
180
+ if @cloud_options
181
+ @cloud_options["plugin"]
182
+ end
183
+ end
184
+
185
+ def cloud
186
+ @lock.synchronize do
187
+ if @cloud.nil?
188
+ plugin = @cloud_options["plugin"]
189
+ properties = @cloud_options["properties"]
190
+ @cloud = Bosh::Clouds::Provider.create(plugin, properties)
191
+ end
192
+ end
193
+ @cloud
194
+ end
195
+
196
+ def logger=(logger)
197
+ @logger = logger
198
+ redis_options[:logger] = @logger
199
+ if redis?
200
+ redis.client.logger = @logger
201
+ end
202
+ end
203
+
204
+ def job_cancelled?
205
+ @current_job.task_checkpoint if @current_job
206
+ end
207
+ alias_method :task_checkpoint, :job_cancelled?
208
+
209
+
210
+ def redis_options
211
+ @redis_options ||= {}
212
+ end
213
+
214
+ def redis_options=(options)
215
+ @redis_options = options
216
+ end
217
+
218
+ def cloud_options=(options)
219
+ @lock.synchronize do
220
+ @cloud_options = options
221
+ @cloud = nil
222
+ end
223
+ end
224
+
225
+ def nats
226
+ @lock.synchronize do
227
+ if @nats.nil?
228
+ @nats = NATS.connect(:uri => @nats_uri, :autostart => false)
229
+ end
230
+ end
231
+ @nats
232
+ end
233
+
234
+ def nats_rpc
235
+ @lock.synchronize do
236
+ if @nats_rpc.nil?
237
+ @nats_rpc = NatsRpc.new
238
+ end
239
+ end
240
+ @nats_rpc
241
+ end
242
+
243
+ def redis
244
+ threaded[:redis] ||= Redis.new(redis_options)
245
+ end
246
+
247
+ def redis?
248
+ !threaded[:redis].nil?
249
+ end
250
+
251
+ def dns_enabled?
252
+ !@dns_db.nil?
253
+ end
254
+
255
+ def encryption?
256
+ @encryption
257
+ end
258
+
259
+ def threaded
260
+ Thread.current[:bosh] ||= {}
261
+ end
262
+
263
+ def patch_sqlite
264
+ return if @patched_sqlite
265
+ @patched_sqlite = true
266
+
267
+ require "sequel"
268
+ require "sequel/adapters/sqlite"
269
+
270
+ Sequel::SQLite::Database.class_eval do
271
+ def connect(server)
272
+ opts = server_opts(server)
273
+ opts[:database] = ':memory:' if blank_object?(opts[:database])
274
+ db = ::SQLite3::Database.new(opts[:database])
275
+ db.busy_handler do |retries|
276
+ Bosh::Director::Config.logger.debug "SQLITE BUSY, retry ##{retries}"
277
+ sleep(0.1)
278
+ retries < 20
279
+ end
280
+
281
+ connection_pragmas.each { |s| log_yield(s) { db.execute_batch(s) } }
282
+
283
+ class << db
284
+ attr_reader :prepared_statements
285
+ end
286
+ db.instance_variable_set(:@prepared_statements, {})
287
+
288
+ db
289
+ end
290
+ end
291
+ end
292
+
293
+ def retrieve_uuid
294
+ directors = Bosh::Director::Models::DirectorAttribute.all
295
+ director = directors.first
296
+
297
+ if directors.size > 1
298
+ @logger.warn("More than one UUID stored in director table, using #{director.uuid}")
299
+ end
300
+
301
+ unless director
302
+ director = Bosh::Director::Models::DirectorAttribute.new
303
+ director.uuid = gen_uuid
304
+ director.save
305
+ @logger.info("Generated director UUID #{director.uuid}")
306
+ end
307
+
308
+ director.uuid
309
+ end
310
+
311
+ def override_uuid
312
+ new_uuid = nil
313
+
314
+ if File.exists?(state_file)
315
+ open(state_file, 'r+') do |file|
316
+
317
+ # lock before read to avoid director/worker race condition
318
+ file.flock(File::LOCK_EX)
319
+ state = Yajl::Parser.parse(file) || {}
320
+ # empty state file to prevent blocked processes from attempting to set UUID
321
+ file.truncate(0)
322
+
323
+ if state["uuid"]
324
+ Bosh::Director::Models::DirectorAttribute.delete
325
+ director = Bosh::Director::Models::DirectorAttribute.new
326
+ director.uuid = state["uuid"]
327
+ director.save
328
+ @logger.info("Using director UUID #{state["uuid"]} from #{state_file}")
329
+ new_uuid = state["uuid"]
330
+ end
331
+
332
+ # unlock after storing UUID
333
+ file.flock(File::LOCK_UN)
334
+ end
335
+
336
+ FileUtils.rm_f(state_file)
337
+ end
338
+
339
+ new_uuid
340
+ end
341
+
342
+ def state_file
343
+ File.join(base_dir, "state.json")
344
+ end
345
+
346
+ def gen_uuid
347
+ SecureRandom.uuid
348
+ end
349
+
350
+ end
351
+
352
+ class << self
353
+ def load_file(path)
354
+ Config.new(Psych.load_file(path))
355
+ end
356
+ def load_hash(hash)
357
+ Config.new(hash)
358
+ end
359
+ end
360
+
361
+ attr_reader :hash
362
+
363
+ private
364
+
365
+ def initialize(hash)
366
+ @hash = hash
367
+ end
368
+
369
+ end
370
+ end
@@ -0,0 +1,114 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::Director
4
+ class ConfigurationHasher
5
+ # @param [DeploymentPlan::Job]
6
+ def initialize(job)
7
+ @job = job
8
+ @logger = Config.logger
9
+ end
10
+
11
+ # @param [DeploymentPlan::Template] template Template to extract
12
+ # @return [String] Path to a directory where template has been extracted
13
+ def extract_template(template)
14
+ temp_path = template.download_blob
15
+ template_dir = Dir.mktmpdir("template_dir")
16
+
17
+ output = `tar -C #{template_dir} -xzf #{temp_path} 2>&1`
18
+ if $?.exitstatus != 0
19
+ raise JobTemplateUnpackFailed,
20
+ "Cannot unpack `#{template.name}' job template, " +
21
+ "tar returned #{$?.exitstatus}, " +
22
+ "tar output: #{output}"
23
+ end
24
+
25
+ template_dir
26
+ ensure
27
+ FileUtils.rm_f(temp_path) if temp_path
28
+ end
29
+
30
+ # @param [DeploymentPlan::Template]
31
+ def process_template(job_template)
32
+ template_dir = extract_template(job_template)
33
+ manifest = Psych.load_file(File.join(template_dir, "job.MF"))
34
+
35
+ monit_template = erb(File.join(template_dir, "monit"))
36
+ monit_template.filename = File.join(job_template.name, "monit")
37
+
38
+ templates = {}
39
+
40
+ if manifest["templates"]
41
+ manifest["templates"].each_key do |template_name|
42
+ template = erb(File.join(template_dir, "templates", template_name))
43
+ templates[template_name] = template
44
+ end
45
+ end
46
+
47
+ @cached_templates[job_template.name] = {
48
+ "templates" => templates,
49
+ "monit_template" => monit_template
50
+ }
51
+ ensure
52
+ FileUtils.rm_rf(template_dir) if template_dir
53
+ end
54
+
55
+ def hash
56
+ @cached_templates = {}
57
+ sorted_jobs = @job.templates.sort { |x, y| x.name <=> y.name }
58
+ sorted_jobs.each do |job_template|
59
+ process_template(job_template)
60
+ end
61
+ @job.instances.each do |instance|
62
+ instance_digest = Digest::SHA1.new
63
+ template_digests = {}
64
+ sorted_jobs.each do |job_template|
65
+ templates = @cached_templates[job_template.name]["templates"]
66
+ monit_template =
67
+ @cached_templates[job_template.name]["monit_template"]
68
+
69
+ binding_helper = Bosh::Common::TemplateEvaluationContext.new(
70
+ instance.spec)
71
+
72
+ bound_templates = bind_template(monit_template, binding_helper,
73
+ instance.index)
74
+
75
+ templates.keys.sort.each do |template_name|
76
+ template = templates[template_name]
77
+ template.filename = File.join(job_template.name, template_name)
78
+ bound_templates << bind_template(template, binding_helper,
79
+ instance.index)
80
+ template_digest = Digest::SHA1.new
81
+ template_digest << bound_templates
82
+ instance_digest << bound_templates
83
+ template_digests[job_template.name] = template_digest.hexdigest
84
+ end
85
+ end
86
+ instance.configuration_hash = instance_digest.hexdigest
87
+ instance.template_hashes = template_digests
88
+ end
89
+ end
90
+
91
+ def bind_template(template, binding_helper, index)
92
+ template.result(binding_helper.get_binding)
93
+ rescue Exception => e
94
+ @logger.debug(e.inspect)
95
+ job_desc = "#{@job.name}/#{index}"
96
+ line_index = e.backtrace.index{ |l| l.include?(template.filename) }
97
+ line = line_index ? e.backtrace[line_index] : '(unknown):(unknown)'
98
+ template_name, line = line.split(':')
99
+
100
+ message = "Error filling in template `#{File.basename(template_name)}' " +
101
+ "for `#{job_desc}' (line #{line}: #{e})"
102
+
103
+ @logger.debug("#{message}\n#{e.backtrace.join("\n")}")
104
+ raise JobTemplateBindingFailed, "#{message}"
105
+ end
106
+
107
+ private
108
+
109
+ def erb(path)
110
+ ERB.new(File.read(path))
111
+ end
112
+
113
+ end
114
+ end