bosh-director 1.2641.0 → 1.2652.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 970adfc1d8041fe7624fc4adf1cad86917730920
4
- data.tar.gz: 6fb6b4ac83b53114782683c85ba45c9ec667ab8e
3
+ metadata.gz: e23095b6bfae1e8e3ef95c3ed35d673812f7ff06
4
+ data.tar.gz: 45d0ef37a600837a982c75cf2c76a012886938a2
5
5
  SHA512:
6
- metadata.gz: 36949611acd25fdcebab2740ad414ea358633c7e0971d477e43775e58330855d52a39faf04c9669ef34842c1b6e2f2b716d265d09903d52a23602458538e81c7
7
- data.tar.gz: fcea68e23b7695ede27826510374db24524032376eeb8ede6e6afdf2a10218777b00c31d9de8250744f9d3a7cd0084e4514290c05c6979d94d594d21f6993d87
6
+ metadata.gz: c98835abd2840e2d857cf7b24207bc26b765a90846170eb760f028b169977202b394da3aeaa5f94f6c74349fd7d76a1f7174004491fc4a74021316434ca9a7e0
7
+ data.tar.gz: 42802d742f68e2539451f63e6b55590c91ee2cf3f98fd7e4a54f58131bba993ee17304ad64c6ba2dbe05adfda9d1baf25b28ca001219fa862996910c38b96f93
@@ -78,4 +78,4 @@ module Bosh::Director
78
78
  end
79
79
  end
80
80
  end
81
- end
81
+ end
@@ -0,0 +1,17 @@
1
+ require 'securerandom'
2
+
3
+ module Bosh::Director
4
+ module Api
5
+ class CompiledPackageGroupManager
6
+ include ApiHelper
7
+
8
+ def create_from_file_path(user, path)
9
+ unless File.exists?(path)
10
+ raise DirectorError, "Failed to import compiled packages: file not found - #{path}"
11
+ end
12
+
13
+ JobQueue.new.enqueue(user, Jobs::ImportCompiledPackages, 'import compiled packages', [path])
14
+ end
15
+ end
16
+ end
17
+ end
@@ -26,14 +26,18 @@ module Bosh::Director
26
26
  @logger = Config.logger
27
27
  end
28
28
 
29
- mime_type :tgz, 'application/x-compressed'
29
+ mime_type :tgz, 'application/x-compressed'
30
+ mime_type :multipart, 'multipart/form-data'
30
31
 
31
32
  def self.consumes(*types)
32
33
  types = Set.new(types)
33
34
  types.map! { |t| mime_type(t) }
34
35
 
35
36
  condition do
36
- types.include?(request.content_type)
37
+ # Content-Type header may include charset or boundry info
38
+ content_type = request.content_type || ''
39
+ mime_type = content_type.split(';')[0]
40
+ types.include?(mime_type)
37
41
  end
38
42
  end
39
43
 
@@ -1,5 +1,6 @@
1
1
  require 'json'
2
2
  require 'tempfile'
3
+ require 'bosh/director/api/compiled_package_group_manager'
3
4
  require 'bosh/director/api/controllers/base_controller'
4
5
  require 'bosh/director/api/stemcell_manager'
5
6
  require 'bosh/director/compiled_package_group'
@@ -10,7 +11,12 @@ require 'bosh/director/jobs/import_compiled_packages'
10
11
  module Bosh::Director
11
12
  module Api::Controllers
12
13
  class CompiledPackagesController < BaseController
13
- post '/compiled_package_groups/export', consumes: [:json] do
14
+ def initialize(*args)
15
+ super
16
+ @compiled_package_group_manager = Api::CompiledPackageGroupManager.new
17
+ end
18
+
19
+ post '/compiled_package_groups/export', consumes: :json do
14
20
  stemcell = find_stemcell_by_name_and_version
15
21
  release_version = find_release_version_by_name_and_version
16
22
 
@@ -30,20 +36,13 @@ module Bosh::Director
30
36
  send_file(output_path, type: :tgz)
31
37
  end
32
38
 
33
- post '/compiled_package_groups/import', consumes: [:tgz] do
34
- tempdir = Dir.mktmpdir
35
- export_path = File.join(tempdir, 'compiled_packages_export.tgz')
36
- # the job is responsible for cleaning this up
37
- File.open(export_path, 'w') do |f|
38
- while buf = request.body.read(4096)
39
- f.write(buf)
40
- end
41
- end
42
-
43
- task = JobQueue.new.enqueue(@user, Jobs::ImportCompiledPackages, 'import compiled packages', [tempdir])
39
+ post '/compiled_package_groups/import', consumes: :multipart do
40
+ task = @compiled_package_group_manager.create_from_file_path(@user, params[:nginx_upload_path])
44
41
  redirect "/tasks/#{task.id}"
45
42
  end
46
43
 
44
+ private
45
+
47
46
  def find_stemcell_by_name_and_version
48
47
  stemcell_manager = Api::StemcellManager.new
49
48
  stemcell_manager.find_by_name_and_version(
@@ -3,37 +3,35 @@ require 'bosh/director/api/controllers/base_controller'
3
3
  module Bosh::Director
4
4
  module Api::Controllers
5
5
  class ReleasesController < BaseController
6
- post '/releases', :consumes => :tgz do
7
- options = {}
8
- options['remote'] = false
9
- options['rebase'] = true if params['rebase'] == 'true'
10
-
11
- task = @release_manager.create_release(@user, request.body, options)
12
- redirect "/tasks/#{task.id}"
13
- end
14
-
15
6
  post '/releases', :consumes => :json do
16
- options = {}
17
- options['remote'] = true
18
- options['rebase'] = true if params['rebase'] == 'true'
19
7
  payload = json_decode(request.body)
8
+ rebase = params['rebase'] == 'true'
9
+ task = @release_manager.create_release_from_url(@user, payload['location'], rebase)
10
+ redirect "/tasks/#{task.id}"
11
+ end
20
12
 
21
- task = @release_manager.create_release(@user, payload['location'], options)
13
+ post '/releases', :consumes => :multipart do
14
+ rebase = params['rebase'] == 'true'
15
+ task = @release_manager.create_release_from_file_path(@user, params[:nginx_upload_path], rebase)
22
16
  redirect "/tasks/#{task.id}"
23
17
  end
24
18
 
25
19
  get '/releases' do
26
20
  releases = Models::Release.order_by(:name.asc).map do |release|
27
21
  release_versions = release.versions_dataset.order_by(:version.asc).map do |rv|
28
- Hash['version', rv.version.to_s,
29
- 'commit_hash', rv.commit_hash,
30
- 'uncommitted_changes', rv.uncommitted_changes,
31
- 'currently_deployed', !rv.deployments.empty?,
32
- 'job_names', rv.templates.map(&:name)]
22
+ {
23
+ 'version' => rv.version.to_s,
24
+ 'commit_hash' => rv.commit_hash,
25
+ 'uncommitted_changes' => rv.uncommitted_changes,
26
+ 'currently_deployed' => !rv.deployments.empty?,
27
+ 'job_names' => rv.templates.map(&:name),
28
+ }
33
29
  end
34
30
 
35
- Hash['name', release.name,
36
- 'release_versions', release_versions]
31
+ {
32
+ 'name' => release.name,
33
+ 'release_versions' => release_versions,
34
+ }
37
35
  end
38
36
 
39
37
  json_encode(releases)
@@ -3,14 +3,14 @@ require 'bosh/director/api/controllers/base_controller'
3
3
  module Bosh::Director
4
4
  module Api::Controllers
5
5
  class StemcellsController < BaseController
6
- post '/stemcells', :consumes => :tgz do
7
- task = @stemcell_manager.create_stemcell(@user, request.body, :remote => false)
6
+ post '/stemcells', :consumes => :json do
7
+ payload = json_decode(request.body)
8
+ task = @stemcell_manager.create_stemcell_from_url(@user, payload['location'])
8
9
  redirect "/tasks/#{task.id}"
9
10
  end
10
11
 
11
- post '/stemcells', :consumes => :json do
12
- payload = json_decode(request.body)
13
- task = @stemcell_manager.create_stemcell(@user, payload['location'], :remote => true)
12
+ post '/stemcells', :consumes => :multipart do
13
+ task = @stemcell_manager.create_stemcell_from_file_path(@user, params[:nginx_upload_path])
14
14
  redirect "/tasks/#{task.id}"
15
15
  end
16
16
 
@@ -3,8 +3,6 @@ module Bosh::Director
3
3
  class ReleaseManager
4
4
  include ApiHelper
5
5
 
6
- RELEASE_TGZ = 'release.tgz'
7
-
8
6
  # Finds release by name
9
7
  # @param [String] name Release name
10
8
  # @return [Models::Release]
@@ -48,21 +46,18 @@ module Bosh::Director
48
46
  release_version
49
47
  end
50
48
 
51
- def create_release(user, release_bundle, options = {})
52
- release_dir = Dir.mktmpdir('release')
53
-
54
- if options['remote']
55
- options['location'] = release_bundle
56
- else
57
- unless check_available_disk_space(release_dir, release_bundle.size)
58
- raise NotEnoughDiskSpace, 'Uploading release archive failed. ' +
59
- "Insufficient space on BOSH director in #{release_dir}"
60
- end
49
+ def create_release_from_url(user, release_url, rebase)
50
+ options = { remote: true, rebase: rebase }
51
+ JobQueue.new.enqueue(user, Jobs::UpdateRelease, 'create release', [release_url, options])
52
+ end
61
53
 
62
- write_file(File.join(release_dir, RELEASE_TGZ), release_bundle)
54
+ def create_release_from_file_path(user, release_path, rebase)
55
+ unless File.exists?(release_path)
56
+ raise DirectorError, "Failed to create release: file not found - #{release_path}"
63
57
  end
64
58
 
65
- JobQueue.new.enqueue(user, Jobs::UpdateRelease, 'create release', [release_dir, options])
59
+ options = { rebase: rebase }
60
+ JobQueue.new.enqueue(user, Jobs::UpdateRelease, 'create release', [release_path, options])
66
61
  end
67
62
 
68
63
  def delete_release(user, release, options = {})
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
1
+ require 'securerandom'
2
2
 
3
3
  module Bosh::Director
4
4
  module Api
@@ -21,23 +21,16 @@ module Bosh::Director
21
21
  false
22
22
  end
23
23
 
24
- def create_stemcell(user, stemcell, options = {})
25
- if options[:remote]
26
- stemcell_file = stemcell
27
- else
28
- random_name = "stemcell-#{SecureRandom.uuid}"
29
- stemcell_dir = Dir::tmpdir
30
- stemcell_file = File.join(stemcell_dir, random_name)
31
-
32
- unless check_available_disk_space(stemcell_dir, stemcell.size)
33
- raise NotEnoughDiskSpace, "Uploading stemcell archive failed. " +
34
- "Insufficient space on BOSH director in #{stemcell_dir}"
35
- end
36
-
37
- write_file(stemcell_file, stemcell)
24
+ def create_stemcell_from_url(user, stemcell_url)
25
+ JobQueue.new.enqueue(user, Jobs::UpdateStemcell, 'create stemcell', [stemcell_url, { remote: true }])
26
+ end
27
+
28
+ def create_stemcell_from_file_path(user, stemcell_path)
29
+ unless File.exists?(stemcell_path)
30
+ raise DirectorError, "Failed to create stemcell: file not found - #{stemcell_path}"
38
31
  end
39
32
 
40
- JobQueue.new.enqueue(user, Jobs::UpdateStemcell, 'create stemcell', [stemcell_file, options])
33
+ JobQueue.new.enqueue(user, Jobs::UpdateStemcell, 'create stemcell', [stemcell_path])
41
34
  end
42
35
 
43
36
  def delete_stemcell(user, stemcell, options={})
@@ -47,4 +40,4 @@ module Bosh::Director
47
40
  end
48
41
  end
49
42
  end
50
- end
43
+ end
@@ -19,6 +19,7 @@ require 'bosh/director/api/release_manager'
19
19
  require 'bosh/director/api/resource_manager'
20
20
  require 'bosh/director/api/snapshot_manager'
21
21
  require 'bosh/director/api/stemcell_manager'
22
+ require 'bosh/director/api/compiled_package_group_manager'
22
23
  require 'bosh/director/api/task_manager'
23
24
  require 'bosh/director/api/user_manager'
24
25
  require 'bosh/director/api/vm_state_manager'
@@ -8,33 +8,34 @@ module Bosh::Director::CompiledPackage
8
8
 
9
9
  def insert(compiled_package, release_version)
10
10
  package = Bosh::Director::Models::Package[fingerprint: compiled_package.package_fingerprint]
11
- stemcell = Bosh::Director::Models::Stemcell[sha1: compiled_package.stemcell_sha1]
12
-
13
11
  raise ArgumentError, [compiled_package.inspect, release_version.inspect].inspect unless package
14
12
 
15
- unless Bosh::Director::Models::CompiledPackage[
13
+ stemcell = Bosh::Director::Models::Stemcell[sha1: compiled_package.stemcell_sha1]
14
+
15
+ compiled_package_model = Bosh::Director::Models::CompiledPackage[
16
16
  package: package,
17
17
  stemcell: stemcell,
18
18
  dependency_key: release_version.package_dependency_key(package.name),
19
19
  ]
20
20
 
21
- oid = File.open(compiled_package.blob_path) do |f|
22
- @blobstore_client.create(f)
23
- end
21
+ return if compiled_package_model
22
+
23
+ oid = File.open(compiled_package.blob_path) do |f|
24
+ @blobstore_client.create(f)
25
+ end
24
26
 
25
- begin
26
- Bosh::Director::Models::CompiledPackage.create(
27
- blobstore_id: oid,
28
- package: package,
29
- stemcell: stemcell,
30
- sha1: compiled_package.sha1,
31
- dependency_key: release_version.package_dependency_key(package.name),
32
- build: Bosh::Director::Models::CompiledPackage.generate_build_number(package, stemcell),
33
- )
34
- rescue
35
- @blobstore_client.delete(oid)
36
- raise
37
- end
27
+ begin
28
+ Bosh::Director::Models::CompiledPackage.create(
29
+ blobstore_id: oid,
30
+ package: package,
31
+ stemcell: stemcell,
32
+ sha1: compiled_package.sha1,
33
+ dependency_key: release_version.package_dependency_key(package.name),
34
+ build: Bosh::Director::Models::CompiledPackage.generate_build_number(package, stemcell),
35
+ )
36
+ rescue
37
+ @blobstore_client.delete(oid)
38
+ raise
38
39
  end
39
40
  end
40
41
  end
@@ -8,11 +8,14 @@ module Bosh::Director::CompiledPackage
8
8
  @exec = options.fetch(:exec, Bosh::Exec)
9
9
  end
10
10
 
11
- def extract(tempdir=nil)
12
- tempdir ||= Dir.mktmpdir
13
- exec.sh("tar -C #{tempdir} -xf #{file}")
14
- manifest = YAML.load_file("#{tempdir}/compiled_packages.MF")
11
+ def extract
12
+ tmp_dir = Dir.mktmpdir
13
+
14
+ @exec.sh("tar -C #{tmp_dir} -xf #{@file}")
15
+
16
+ manifest = YAML.load_file("#{tmp_dir}/compiled_packages.MF")
15
17
  packages = []
18
+
16
19
  manifest['compiled_packages'].each do |p|
17
20
  packages << CompiledPackage.new(
18
21
  package_name: p['package_name'],
@@ -20,16 +23,13 @@ module Bosh::Director::CompiledPackage
20
23
  sha1: p['compiled_package_sha1'],
21
24
  stemcell_sha1: p['stemcell_sha1'],
22
25
  blobstore_id: p['blobstore_id'],
23
- blob_path: File.join(tempdir, 'compiled_packages', 'blobs', p['blobstore_id']))
26
+ blob_path: File.join(tmp_dir, 'compiled_packages', 'blobs', p['blobstore_id']),
27
+ )
24
28
  end
25
29
 
26
30
  yield manifest, packages
27
31
 
28
- FileUtils.rm_rf(tempdir)
32
+ FileUtils.rm_rf(tmp_dir)
29
33
  end
30
-
31
- private
32
-
33
- attr_reader :file, :exec
34
34
  end
35
35
  end
@@ -41,7 +41,7 @@ module Bosh::Director
41
41
  attr_accessor option
42
42
  end
43
43
 
44
- attr_reader :db_config
44
+ attr_reader :db_config, :redis_logger_level
45
45
 
46
46
  def clear
47
47
  CONFIG_OPTIONS.each do |option|
@@ -75,14 +75,14 @@ module Bosh::Director
75
75
  logging = config.fetch('logging', {})
76
76
  @log_device = MonoLogger::LocklessLogDevice.new(logging.fetch('file', STDOUT))
77
77
  @logger = MonoLogger.new(@log_device)
78
- @logger.level = MonoLogger.const_get(logging.fetch('level', 'debug').upcase)
78
+ @logger.level = Logger.const_get(logging.fetch('level', 'debug').upcase)
79
79
  @logger.formatter = ThreadFormatter.new
80
80
 
81
81
  # use a separate logger for redis to make it stfu
82
82
  redis_logger = MonoLogger.new(@log_device)
83
83
  logging = config.fetch('redis', {}).fetch('logging', {})
84
- redis_logger_level = logging.fetch('level', 'info').upcase
85
- redis_logger.level = MonoLogger.const_get(redis_logger_level)
84
+ @redis_logger_level = Logger.const_get(logging.fetch('level', 'info').upcase)
85
+ redis_logger.level = @redis_logger_level
86
86
 
87
87
  # Event logger supposed to be overridden per task,
88
88
  # the default one does nothing
@@ -93,7 +93,7 @@ module Bosh::Director
93
93
 
94
94
  @max_threads = config.fetch('max_threads', 32).to_i
95
95
 
96
- self.redis_options= {
96
+ self.redis_options = {
97
97
  :host => config['redis']['host'],
98
98
  :port => config['redis']['port'],
99
99
  :password => config['redis']['password'],
@@ -201,24 +201,20 @@ module Bosh::Director
201
201
  Config.cloud_options.fetch('properties', {}).fetch('cpi_log')
202
202
  end
203
203
 
204
- def logger=(logger)
205
- @logger = logger
206
- redis_options[:logger] = @logger
207
- if redis?
208
- redis.client.logger = @logger
209
- end
210
- end
211
-
212
204
  def job_cancelled?
213
205
  @current_job.task_checkpoint if @current_job
214
206
  end
215
- alias_method :task_checkpoint, :job_cancelled?
216
207
 
208
+ alias_method :task_checkpoint, :job_cancelled?
217
209
 
218
210
  def redis_options
219
211
  @redis_options ||= {}
220
212
  end
221
213
 
214
+ def redis_logger_level
215
+ @redis_logger_level || Logger::INFO
216
+ end
217
+
222
218
  def redis_options=(options)
223
219
  @redis_options = options
224
220
  end
@@ -252,6 +248,14 @@ module Bosh::Director
252
248
  threaded[:redis] ||= Redis.new(redis_options)
253
249
  end
254
250
 
251
+ def redis_logger=(logger)
252
+ if redis?
253
+ redis.client.logger = logger
254
+ else
255
+ redis_options[:logger] = logger
256
+ end
257
+ end
258
+
255
259
  def redis?
256
260
  !threaded[:redis].nil?
257
261
  end
@@ -346,6 +350,5 @@ module Bosh::Director
346
350
  def initialize(hash)
347
351
  @hash = hash
348
352
  end
349
-
350
353
  end
351
354
  end
@@ -1,12 +1,10 @@
1
+ require 'net/http'
2
+ require 'timeout'
3
+ require 'uri'
4
+
1
5
  module Bosh::Director
2
6
  module DownloadHelper
3
- require 'net/http'
4
- require 'timeout'
5
- require 'uri'
6
-
7
- ##
8
7
  # Downloads a remote file
9
- #
10
8
  # @param [String] resource Resource name to be logged
11
9
  # @param [String] remote_file Remote file to download
12
10
  # @param [String] local_file Local file to store the downloaded file
@@ -41,4 +39,4 @@ module Bosh::Director
41
39
  raise ResourceError, "Downloading remote #{resource} failed. Check task debug log for details."
42
40
  end
43
41
  end
44
- end
42
+ end
@@ -1,5 +1,3 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
1
  module Resque
4
2
  def redis
5
3
  Bosh::Director::Config.redis
@@ -7,15 +5,15 @@ module Resque
7
5
  end
8
6
 
9
7
  class Object
10
- def to_openstruct
11
- self
12
- end
8
+ def to_openstruct
9
+ self
10
+ end
13
11
  end
14
12
 
15
13
  class Array
16
- def to_openstruct
17
- map { |el| el.to_openstruct }
18
- end
14
+ def to_openstruct
15
+ map { |el| el.to_openstruct }
16
+ end
19
17
  end
20
18
 
21
19
  class Hash
@@ -30,35 +28,9 @@ class Hash
30
28
  self
31
29
  end
32
30
 
33
- def to_openstruct
34
- mapped = {}
35
- each { |key, value| mapped[key] = value.to_openstruct }
36
- OpenStruct.new(mapped)
37
- end
38
- end
39
-
40
- require "sequel/connection_pool/threaded"
41
-
42
- class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
43
-
44
- alias_method :acquire_original, :acquire
45
- alias_method :release_original, :release
46
-
47
- def acquire(thread)
48
- logger = Bosh::Director::Config.logger
49
- result = acquire_original(thread)
50
- if logger
51
- logger.debug("Acquired connection: #{@allocated[thread].object_id}")
52
- end
53
- result
54
- end
55
-
56
- def release(thread)
57
- logger = Bosh::Director::Config.logger
58
- if logger
59
- logger.debug("Released connection: #{@allocated[thread].object_id}")
60
- end
61
- release_original(thread)
31
+ def to_openstruct
32
+ mapped = {}
33
+ each { |key, value| mapped[key] = value.to_openstruct }
34
+ OpenStruct.new(mapped)
62
35
  end
63
-
64
36
  end
@@ -53,7 +53,9 @@ module Bosh::Director
53
53
  event_log = File.join(log_dir, 'event')
54
54
  result_log = File.join(log_dir, 'result')
55
55
 
56
- @task_logger = MonoLogger.new(debug_log)
56
+ debug_log_device = MonoLogger::LocklessLogDevice.new(debug_log)
57
+
58
+ @task_logger = MonoLogger.new(debug_log_device)
57
59
  @task_logger.level = Config.logger.level
58
60
  @task_logger.formatter = ThreadFormatter.new
59
61
 
@@ -61,6 +63,11 @@ module Bosh::Director
61
63
  Config.result = TaskResultFile.new(result_log)
62
64
  Config.logger = @task_logger
63
65
 
66
+ redis_task_logger = MonoLogger.new(debug_log_device)
67
+ redis_task_logger.level = Config.redis_logger_level
68
+ redis_task_logger.formatter = ThreadFormatter.new
69
+ Config.redis_logger = redis_task_logger
70
+
64
71
  Config.db.logger = @task_logger
65
72
 
66
73
  if Config.dns_enabled?
@@ -10,14 +10,13 @@ module Bosh::Director
10
10
  :import_compiled_packages
11
11
  end
12
12
 
13
- def initialize(export_dir)
14
- @export_dir = export_dir
15
-
13
+ def initialize(compiled_packages_path)
14
+ @compiled_packages_path = compiled_packages_path
16
15
  @blobstore_client = Bosh::Director::App.instance.blobstores.blobstore
17
16
  end
18
17
 
19
18
  def perform
20
- export = Bosh::Director::CompiledPackage::CompiledPackagesExport.new(file: export_path)
19
+ export = Bosh::Director::CompiledPackage::CompiledPackagesExport.new(file: @compiled_packages_path)
21
20
 
22
21
  export.extract do |manifest, packages|
23
22
  release_name = manifest.fetch('release_name')
@@ -38,17 +37,8 @@ module Bosh::Director
38
37
  end
39
38
  end
40
39
  ensure
41
- FileUtils.rm_rf(@export_dir)
40
+ FileUtils.rm_rf(@compiled_packages_path)
42
41
  end
43
-
44
- private
45
-
46
- def export_path
47
- File.join(@export_dir, 'compiled_packages_export.tgz')
48
- end
49
-
50
- attr_reader :blobstore_client
51
- attr_reader :export_dir
52
42
  end
53
43
  end
54
44
  end
@@ -1,5 +1,4 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
1
+ require 'securerandom'
3
2
  require 'common/version/release_version'
4
3
 
5
4
  module Bosh::Director
@@ -11,20 +10,27 @@ module Bosh::Director
11
10
  @queue = :normal
12
11
 
13
12
  attr_accessor :release_model
14
- attr_accessor :tmp_release_dir
15
13
 
16
14
  def self.job_type
17
15
  :update_release
18
16
  end
19
17
 
20
- # @param [String] tmp_release_dir Directory containing release bundle
18
+ # @param [String] release_path local path or remote url of the release archive
21
19
  # @param [Hash] options Release update options
22
- def initialize(tmp_release_dir, options = {})
23
- @tmp_release_dir = tmp_release_dir
20
+ def initialize(release_path, options = {})
21
+ if options['remote']
22
+ # file will be downloaded to the release_path
23
+ @release_path = File.join(Dir.tmpdir, "release-#{SecureRandom.uuid}")
24
+ @release_url = release_path
25
+ else
26
+ # file already exists at the release_path
27
+ @release_path = release_path
28
+ end
29
+
24
30
  @release_model = nil
25
31
  @release_version_model = nil
26
32
 
27
- @rebase = !!options["rebase"]
33
+ @rebase = !!options['rebase']
28
34
 
29
35
  @manifest = nil
30
36
  @name = nil
@@ -32,68 +38,62 @@ module Bosh::Director
32
38
 
33
39
  @packages_unchanged = false
34
40
  @jobs_unchanged = false
35
-
36
- @remote_release = options['remote'] || false
37
- @remote_release_location = options['location'] if @remote_release
38
41
  end
39
42
 
40
- # Extracts release tarball, verifies release manifest and saves release
41
- # in DB
43
+ # Extracts release tarball, verifies release manifest and saves release in DB
42
44
  # @return [void]
43
45
  def perform
44
46
  logger.info("Processing update release")
45
- if @rebase
46
- logger.info("Release rebase will be performed")
47
- end
47
+ logger.info("Release rebase will be performed") if @rebase
48
+
49
+ single_step_stage("Downloading remote release") { download_remote_release } if @release_url
48
50
 
49
- single_step_stage("Downloading remote release") { download_remote_release } if @remote_release
50
- single_step_stage("Extracting release") { extract_release }
51
- single_step_stage("Verifying manifest") { verify_manifest }
51
+ release_dir = nil
52
+ single_step_stage("Extracting release") { release_dir = extract_release }
52
53
 
53
- with_release_lock(@name) { process_release }
54
+ single_step_stage("Verifying manifest") { verify_manifest(release_dir) }
55
+
56
+ with_release_lock(@name) { process_release(release_dir) }
54
57
 
55
58
  if @rebase && @packages_unchanged && @jobs_unchanged
56
- raise DirectorError,
57
- "Rebase is attempted without any job or package changes"
59
+ raise DirectorError, "Rebase is attempted without any job or package changes"
58
60
  end
59
61
 
60
62
  "Created release `#{@name}/#{@version}'"
63
+
61
64
  rescue Exception => e
62
65
  remove_release_version_model
63
66
  raise e
67
+
64
68
  ensure
65
- if @tmp_release_dir && File.exists?(@tmp_release_dir)
66
- FileUtils.rm_rf(@tmp_release_dir)
67
- end
69
+ FileUtils.rm_rf(release_dir) if release_dir
70
+ FileUtils.rm_rf(@release_path) if @release_path
68
71
  end
69
72
 
70
73
  def download_remote_release
71
- release_file = File.join(@tmp_release_dir, Api::ReleaseManager::RELEASE_TGZ)
72
- download_remote_file('release', @remote_release_location, release_file)
74
+ download_remote_file('release', @release_url, @release_path)
73
75
  end
74
76
 
75
77
  # Extracts release tarball
76
78
  # @return [void]
77
79
  def extract_release
78
- release_tgz = File.join(@tmp_release_dir,
79
- Api::ReleaseManager::RELEASE_TGZ)
80
+ release_dir = Dir.mktmpdir
80
81
 
81
- result = Bosh::Exec.sh("tar -C #{@tmp_release_dir} -xzf #{release_tgz} 2>&1", :on_error => :return)
82
+ result = Bosh::Exec.sh("tar -C #{release_dir} -xzf #{@release_path} 2>&1", :on_error => :return)
82
83
  if result.failed?
83
- logger.error("Extracting release archive failed in dir #{@tmp_release_dir}, " +
84
+ logger.error("Failed to extract release archive '#{@release_path}' into dir '#{release_dir}', " +
84
85
  "tar returned #{result.exit_status}, " +
85
86
  "output: #{result.output}")
86
87
  raise ReleaseInvalidArchive, "Extracting release archive failed. Check task debug log for details."
87
88
  end
88
- ensure
89
- if release_tgz && File.exists?(release_tgz)
90
- FileUtils.rm(release_tgz)
91
- end
89
+
90
+ release_dir
92
91
  end
93
92
 
93
+ # @param [String] release_dir local path to the unpacked release
94
94
  # @return [void]
95
- def verify_manifest
96
- manifest_file = File.join(@tmp_release_dir, "release.MF")
95
+ def verify_manifest(release_dir)
96
+ manifest_file = File.join(release_dir, "release.MF")
97
97
  unless File.file?(manifest_file)
98
98
  raise ReleaseManifestNotFound, "Release manifest not found"
99
99
  end
@@ -117,8 +117,9 @@ module Bosh::Director
117
117
  end
118
118
 
119
119
  # Processes uploaded release, creates jobs and packages in DB if needed
120
+ # @param [String] release_dir local path to the unpacked release
120
121
  # @return [void]
121
- def process_release
122
+ def process_release(release_dir)
122
123
  @release_model = Models::Release.find_or_create(:name => @name)
123
124
 
124
125
  if @rebase
@@ -150,8 +151,8 @@ module Bosh::Director
150
151
  end
151
152
 
152
153
  @packages = {}
153
- process_packages
154
- process_jobs
154
+ process_packages(release_dir)
155
+ process_jobs(release_dir)
155
156
 
156
157
  event_log.begin_stage("Release has been created", 1)
157
158
  event_log.track("#{@name}/#{@version}") {}
@@ -197,8 +198,9 @@ module Bosh::Director
197
198
  # Finds all package definitions in the manifest and sorts them into two
198
199
  # buckets: new and existing packages, then creates new packages and points
199
200
  # current release version to the existing packages.
201
+ # @param [String] release_dir local path to the unpacked release
200
202
  # @return [void]
201
- def process_packages
203
+ def process_packages(release_dir)
202
204
  logger.info("Checking for new packages in release")
203
205
 
204
206
  new_packages = []
@@ -232,14 +234,15 @@ module Bosh::Director
232
234
  end
233
235
  end
234
236
 
235
- create_packages(new_packages)
237
+ create_packages(new_packages, release_dir)
236
238
  use_existing_packages(existing_packages)
237
239
  end
238
240
 
239
241
  # Creates packages using provided metadata
240
242
  # @param [Array<Hash>] packages Packages metadata
243
+ # @param [String] release_dir local path to the unpacked release
241
244
  # @return [void]
242
- def create_packages(packages)
245
+ def create_packages(packages, release_dir)
243
246
  if packages.empty?
244
247
  @packages_unchanged = true
245
248
  return
@@ -250,7 +253,7 @@ module Bosh::Director
250
253
  package_desc = "#{package_meta["name"]}/#{package_meta["version"]}"
251
254
  event_log.track(package_desc) do
252
255
  logger.info("Creating new package `#{package_desc}'")
253
- package = create_package(package_meta)
256
+ package = create_package(package_meta, release_dir)
254
257
  register_package(package)
255
258
  end
256
259
  end
@@ -272,8 +275,9 @@ module Bosh::Director
272
275
 
273
276
  # Creates package in DB according to given metadata
274
277
  # @param [Hash] package_meta Package metadata
278
+ # @param [String] release_dir local path to the unpacked release
275
279
  # @return [void]
276
- def create_package(package_meta)
280
+ def create_package(package_meta, release_dir)
277
281
  name, version = package_meta["name"], package_meta["version"]
278
282
 
279
283
  package_attrs = {
@@ -296,7 +300,7 @@ module Bosh::Director
296
300
  else
297
301
  logger.info("Creating #{desc} from provided bits")
298
302
 
299
- package_tgz = File.join(@tmp_release_dir, "packages", "#{name}.tgz")
303
+ package_tgz = File.join(release_dir, "packages", "#{name}.tgz")
300
304
  result = Bosh::Exec.sh("tar -tzf #{package_tgz} 2>&1", :on_error => :return)
301
305
  if result.failed?
302
306
  logger.error("Extracting #{desc} archive failed, " +
@@ -322,8 +326,9 @@ module Bosh::Director
322
326
  # Finds job template definitions in release manifest and sorts them into
323
327
  # two buckets: new and existing job templates, then creates new job
324
328
  # template records in the database and points release version to existing ones.
329
+ # @param [String] release_dir local path to the unpacked release
325
330
  # @return [void]
326
- def process_jobs
331
+ def process_jobs(release_dir)
327
332
  logger.info("Checking for new jobs in release")
328
333
 
329
334
  new_jobs = []
@@ -346,11 +351,11 @@ module Bosh::Director
346
351
  end
347
352
  end
348
353
 
349
- create_jobs(new_jobs)
354
+ create_jobs(new_jobs, release_dir)
350
355
  use_existing_jobs(existing_jobs)
351
356
  end
352
357
 
353
- def create_jobs(jobs)
358
+ def create_jobs(jobs, release_dir)
354
359
  if jobs.empty?
355
360
  @jobs_unchanged = true
356
361
  return
@@ -361,13 +366,13 @@ module Bosh::Director
361
366
  job_desc = "#{job_meta["name"]}/#{job_meta["version"]}"
362
367
  event_log.track(job_desc) do
363
368
  logger.info("Creating new template `#{job_desc}'")
364
- template = create_job(job_meta)
369
+ template = create_job(job_meta, release_dir)
365
370
  register_template(template)
366
371
  end
367
372
  end
368
373
  end
369
374
 
370
- def create_job(job_meta)
375
+ def create_job(job_meta, release_dir)
371
376
  name, version = job_meta["name"], job_meta["version"]
372
377
 
373
378
  template_attrs = {
@@ -382,8 +387,8 @@ module Bosh::Director
382
387
  "from provided bits")
383
388
  template = Models::Template.new(template_attrs)
384
389
 
385
- job_tgz = File.join(@tmp_release_dir, "jobs", "#{name}.tgz")
386
- job_dir = File.join(@tmp_release_dir, "jobs", "#{name}")
390
+ job_tgz = File.join(release_dir, "jobs", "#{name}.tgz")
391
+ job_dir = File.join(release_dir, "jobs", "#{name}")
387
392
 
388
393
  FileUtils.mkdir_p(job_dir)
389
394
 
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
1
+ require 'securerandom'
2
2
 
3
3
  module Bosh::Director
4
4
  module Jobs
@@ -14,27 +14,33 @@ module Bosh::Director
14
14
  :update_stemcell
15
15
  end
16
16
 
17
- # @param [String] stemcell_file Stemcell tarball path
18
- def initialize(stemcell_file, options = {})
19
- @stemcell_file = stemcell_file
17
+ # @param [String] stemcell_path local path or remote url of the stemcell archive
18
+ # @param [Hash] options Stemcell update options
19
+ def initialize(stemcell_path, options = {})
20
+ if options['remote']
21
+ # file will be downloaded to the stemcell_path
22
+ @stemcell_path = File.join(Dir.tmpdir, "stemcell-#{SecureRandom.uuid}")
23
+ @stemcell_url = stemcell_path
24
+ else
25
+ # file already exists at the stemcell_path
26
+ @stemcell_path = stemcell_path
27
+ end
28
+
20
29
  @cloud = Config.cloud
21
30
  @stemcell_manager = Api::StemcellManager.new
22
- @remote_stemcell = options['remote'] || false
23
31
  end
24
32
 
25
33
  def perform
26
34
  logger.info("Processing update stemcell")
27
- event_log.begin_stage("Update stemcell", update_steps)
28
35
 
29
- if @remote_stemcell
30
- downloaded_stemcell_dir = Dir.mktmpdir("downloaded-stemcell")
31
- download_remote_stemcell(downloaded_stemcell_dir)
32
- end
33
-
36
+ event_log.begin_stage("Update stemcell", @stemcell_url ? UPDATE_STEPS + 1 : UPDATE_STEPS)
37
+
38
+ track_and_log("Downloading remote stemcell") { download_remote_stemcell } if @stemcell_url
39
+
34
40
  stemcell_dir = Dir.mktmpdir("stemcell")
35
41
 
36
42
  track_and_log("Extracting stemcell archive") do
37
- result = Bosh::Exec.sh("tar -C #{stemcell_dir} -xzf #{@stemcell_file} 2>&1", :on_error => :return)
43
+ result = Bosh::Exec.sh("tar -C #{stemcell_dir} -xzf #{@stemcell_path} 2>&1", :on_error => :return)
38
44
  if result.failed?
39
45
  logger.error("Extracting stemcell archive failed in dir #{stemcell_dir}, " +
40
46
  "tar returned #{result.exit_status}, " +
@@ -75,8 +81,7 @@ module Bosh::Director
75
81
  stemcell.sha1 = @sha1
76
82
 
77
83
  track_and_log("Uploading stemcell #{@name}/#{@version} to the cloud") do
78
- stemcell.cid =
79
- @cloud.create_stemcell(@stemcell_image, @cloud_properties)
84
+ stemcell.cid = @cloud.create_stemcell(@stemcell_image, @cloud_properties)
80
85
  logger.info("Cloud created stemcell: #{stemcell.cid}")
81
86
  end
82
87
 
@@ -87,22 +92,13 @@ module Bosh::Director
87
92
  "/stemcells/#{stemcell.name}/#{stemcell.version}"
88
93
  ensure
89
94
  FileUtils.rm_rf(stemcell_dir) if stemcell_dir
90
- FileUtils.rm_rf(downloaded_stemcell_dir) if downloaded_stemcell_dir
91
- FileUtils.rm_rf(@stemcell_file) if @stemcell_file
92
- end
93
-
94
- def download_remote_stemcell(downloaded_stemcell_dir)
95
- track_and_log("Downloading remote stemcell") do
96
- downloaded_stemcell_file = File.join(downloaded_stemcell_dir, "stemcell-#{SecureRandom.uuid}")
97
- download_remote_file('stemcell', @stemcell_file, downloaded_stemcell_file)
98
- @stemcell_file = downloaded_stemcell_file
99
- end
95
+ FileUtils.rm_rf(@stemcell_path) if @stemcell_path
100
96
  end
101
97
 
102
98
  private
103
-
104
- def update_steps
105
- @remote_stemcell ? UPDATE_STEPS + 1 : UPDATE_STEPS
99
+
100
+ def download_remote_stemcell
101
+ download_remote_file('stemcell', @stemcell_url, @stemcell_path)
106
102
  end
107
103
  end
108
104
  end
@@ -1,5 +1,5 @@
1
1
  module Bosh
2
2
  module Director
3
- VERSION = '1.2641.0'
3
+ VERSION = '1.2652.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bosh-director
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2641.0
4
+ version: 1.2652.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - VMware
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-11 00:00:00.000000000 Z
11
+ date: 2014-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bcrypt-ruby
@@ -30,126 +30,126 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.2641.0
33
+ version: 1.2652.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.2641.0
40
+ version: 1.2652.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bosh-core
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.2641.0
47
+ version: 1.2652.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 1.2641.0
54
+ version: 1.2652.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bosh-director-core
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 1.2641.0
61
+ version: 1.2652.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 1.2641.0
68
+ version: 1.2652.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: bosh_common
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 1.2641.0
75
+ version: 1.2652.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 1.2641.0
82
+ version: 1.2652.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: bosh_cpi
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 1.2641.0
89
+ version: 1.2652.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 1.2641.0
96
+ version: 1.2652.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: bosh_openstack_cpi
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 1.2641.0
103
+ version: 1.2652.0
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 1.2641.0
110
+ version: 1.2652.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: bosh_aws_cpi
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 1.2641.0
117
+ version: 1.2652.0
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: 1.2641.0
124
+ version: 1.2652.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: bosh_vsphere_cpi
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 1.2641.0
131
+ version: 1.2652.0
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: 1.2641.0
138
+ version: 1.2652.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: bosh_warden_cpi
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 1.2641.0
145
+ version: 1.2652.0
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 1.2641.0
152
+ version: 1.2652.0
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: bosh_vcloud_cpi
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -446,7 +446,7 @@ dependencies:
446
446
  version: '0'
447
447
  description: |-
448
448
  BOSH Director
449
- 23fe6f
449
+ 43d2e8
450
450
  email: support@cloudfoundry.com
451
451
  executables:
452
452
  - bosh-director
@@ -502,6 +502,7 @@ files:
502
502
  - lib/bosh/director/api.rb
503
503
  - lib/bosh/director/api/api_helper.rb
504
504
  - lib/bosh/director/api/backup_manager.rb
505
+ - lib/bosh/director/api/compiled_package_group_manager.rb
505
506
  - lib/bosh/director/api/controller.rb
506
507
  - lib/bosh/director/api/controller_helpers.rb
507
508
  - lib/bosh/director/api/controllers/backups_controller.rb