bosh-director 1.3022.0 → 1.3048.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: 59a2d6077683ae1eaac10b9926fd87139cbf2193
4
- data.tar.gz: e417875f5b9b4311ca2ffc19cbea42a4b4e673ed
3
+ metadata.gz: 99e55b602be5167be9b84464a78041c5062b3a6b
4
+ data.tar.gz: 50a15495b6c79bba2264981fa4fe07158d6456ed
5
5
  SHA512:
6
- metadata.gz: fc4627b56956d3e9ce4795286416798815f1475b5542aee9b7de375f1b8c6b64f083b02b93db041e3530ab799f63732bc67bd3e87662e131ffd81c9dcd8216c5
7
- data.tar.gz: c0d98a660d38ed280d769427e1ba7adb37e66426a2ccd7d46156c582194d0950eb6628a68999e257db3a92dd79871eeb8b29a954d8a29b01d303a82e744f6cec
6
+ metadata.gz: 16088e13da325245d18e3f0c45983f1fd288459acb7411475c15a4a7a141b6ae53a62a774ee4b93ccd768e6a987f544e8d16f0956e79884762e484777b53a6a7
7
+ data.tar.gz: 2ec85bdee426f93026360a03aac14b8b86dca556ce2f60ce6e55f29d3861ab5dbb500c401a4c4e42c193edd366597b9ff2a0f999bbff86efe272d2ccbe1ca0ce
@@ -52,59 +52,68 @@ module Bosh::Director
52
52
  end
53
53
 
54
54
  def method_missing(method_name, *args)
55
- send_message(method_name, *args)
56
- end
57
-
58
- # Define methods on this class to make instance_double more useful
59
- [
60
- :cancel_task,
61
- :get_state,
62
- :get_task,
63
- :list_disk,
64
- :prepare_network_change,
65
- :prepare_configure_networks,
66
- :start,
67
- ].each do |message|
68
- define_method(message) do |*args|
69
- send_message(message, *args)
70
- end
55
+ handle_message_with_retry(method_name, *args)
56
+ end
57
+
58
+ def get_state(*args)
59
+ send_message(:get_state, *args)
60
+ end
61
+
62
+ def cancel_task(*args)
63
+ send_message(:cancel_task, *args)
64
+ end
65
+
66
+ def list_disk(*args)
67
+ send_message(:list_disk, *args)
68
+ end
69
+
70
+ def prepare_configure_networks(*args)
71
+ send_message(:prepare_configure_networks, *args)
72
+ end
73
+
74
+ def prepare_network_change(*args)
75
+ send_message(:prepare_network_change, *args)
76
+ end
77
+
78
+ def start(*args)
79
+ send_message(:start, *args)
71
80
  end
72
81
 
73
82
  def prepare(*args)
74
- send_long_running_message(:prepare, *args)
83
+ send_message(:prepare, *args)
75
84
  end
76
85
 
77
86
  def apply(*args)
78
- send_long_running_message(:apply, *args)
87
+ send_message(:apply, *args)
79
88
  end
80
89
 
81
90
  def compile_package(*args)
82
- send_long_running_message(:compile_package, *args)
91
+ send_message(:compile_package, *args)
83
92
  end
84
93
 
85
94
  def drain(*args)
86
- send_long_running_message(:drain, *args)
95
+ send_message(:drain, *args)
87
96
  end
88
97
 
89
98
  def fetch_logs(*args)
90
- send_long_running_message(:fetch_logs, *args)
99
+ send_message(:fetch_logs, *args)
91
100
  end
92
101
 
93
102
  def migrate_disk(*args)
94
- send_long_running_message(:migrate_disk, *args)
103
+ send_message(:migrate_disk, *args)
95
104
  end
96
105
 
97
106
  def mount_disk(*args)
98
- send_long_running_message(:mount_disk, *args)
107
+ send_message(:mount_disk, *args)
99
108
  end
100
109
 
101
110
  def unmount_disk(*args)
102
- send_long_running_message(:unmount_disk, *args)
111
+ send_message(:unmount_disk, *args)
103
112
  end
104
113
 
105
114
  def update_settings(certs)
106
115
  begin
107
- send_long_running_message(:update_settings, {"trusted_certs" => certs})
116
+ send_message(:update_settings, {"trusted_certs" => certs})
108
117
  rescue RpcRemoteException => e
109
118
  if e.message =~ /unknown message/
110
119
  @logger.warn("Ignoring update_settings 'unknown message' error from the agent: #{e.inspect}")
@@ -115,11 +124,11 @@ module Bosh::Director
115
124
  end
116
125
 
117
126
  def stop(*args)
118
- send_long_running_message(:stop, *args)
127
+ send_message(:stop, *args)
119
128
  end
120
129
 
121
- def start_errand(*args)
122
- start_long_running_task(:run_errand, *args)
130
+ def run_errand(*args)
131
+ start_task(:run_errand, *args)
123
132
  end
124
133
 
125
134
  def wait_for_task(agent_task_id, &blk)
@@ -135,7 +144,7 @@ module Bosh::Director
135
144
  end
136
145
 
137
146
  def configure_networks(*args)
138
- send_long_running_message(:configure_networks, *args)
147
+ send_message(:configure_networks, *args)
139
148
  end
140
149
 
141
150
  def wait_until_ready(deadline = 600)
@@ -196,8 +205,8 @@ module Bosh::Director
196
205
  unless timeout > 0
197
206
  @nats_rpc.cancel_request(request_id)
198
207
  raise RpcTimeout,
199
- "Timed out sending `#{method_name}' to #{@client_id} " +
200
- "after #{@timeout} seconds"
208
+ "Timed out sending `#{method_name}' to #{@client_id} " +
209
+ "after #{@timeout} seconds"
201
210
  end
202
211
  cond.wait(timeout)
203
212
  end
@@ -256,7 +265,7 @@ module Bosh::Director
256
265
  @resource_manager.delete_resource(blob_id)
257
266
  end
258
267
 
259
- def send_message(message_name, *args)
268
+ def handle_message_with_retry(message_name, *args)
260
269
  retries = @retry_methods[message_name] || 0
261
270
  begin
262
271
  handle_method(message_name, args)
@@ -269,13 +278,17 @@ module Bosh::Director
269
278
  end
270
279
  end
271
280
 
272
- def send_long_running_message(method_name, *args, &blk)
273
- task = start_long_running_task(method_name, *args)
274
- wait_for_task(task['agent_task_id'], &blk)
281
+ def send_message(method_name, *args, &blk)
282
+ task = start_task(method_name, *args)
283
+ if task['agent_task_id']
284
+ wait_for_task(task['agent_task_id'], &blk)
285
+ else
286
+ task['value']
287
+ end
275
288
  end
276
289
 
277
- def start_long_running_task(method_name, *args)
278
- AgentMessageConverter.convert_old_message_to_new(send_message(method_name, *args))
290
+ def start_task(method_name, *args)
291
+ AgentMessageConverter.convert_old_message_to_new(handle_message_with_retry(method_name, *args))
279
292
  end
280
293
 
281
294
  def get_task_status(agent_task_id)
@@ -48,7 +48,7 @@ module Bosh::Director
48
48
  redirect "/tasks/#{task.id}"
49
49
  end
50
50
 
51
- # PUT /deployments/foo/jobs/dea/2?state={started,stopped,detached,restart,recreate}
51
+ # PUT /deployments/foo/jobs/dea/2?state={started,stopped,detached,restart,recreate}&skip_drain=true
52
52
  put '/:deployment/jobs/:job/:index', :consumes => :yaml do
53
53
  begin
54
54
  index = Integer(params[:index])
@@ -61,9 +61,10 @@ module Bosh::Director
61
61
  params[:job] => {
62
62
  'instance_states' => {
63
63
  index => params['state']
64
- }
64
+ },
65
65
  }
66
- }
66
+ },
67
+ 'skip_drain' => params[:job]
67
68
  }
68
69
 
69
70
  deployment = @deployment_manager.find_by_name(params[:deployment])
@@ -269,6 +270,7 @@ module Bosh::Director
269
270
  post '/', :consumes => :yaml do
270
271
  options = {}
271
272
  options['recreate'] = true if params['recreate'] == 'true'
273
+ options['skip_drain'] = params['skip_drain'] if params['skip_drain']
272
274
  latest_cloud_config = Bosh::Director::Api::CloudConfigManager.new.latest
273
275
 
274
276
  task = @deployment_manager.create_deployment(current_user, request.body, latest_cloud_config, options)
@@ -313,7 +315,6 @@ module Bosh::Director
313
315
  planner_factory.planner_without_vm_binding(manifest_hash, cloud_config_model, {})
314
316
  end
315
317
 
316
-
317
318
  def convert_job_instance_hash(hash)
318
319
  hash.reduce([]) do |jobs, kv|
319
320
  job, indicies = kv
@@ -16,7 +16,6 @@ module Bosh::Director
16
16
  post '/', :consumes => :multipart do
17
17
  options = {
18
18
  rebase: params['rebase'] == 'true',
19
- compiled: params['compiled'] == 'true',
20
19
  }
21
20
 
22
21
  task = @release_manager.create_release_from_file_path(current_user, params[:nginx_upload_path], options)
@@ -61,6 +60,11 @@ module Bosh::Director
61
60
 
62
61
  get '/:name', scope: :read do
63
62
  name = params[:name].to_s.strip
63
+
64
+ if params['version']
65
+ return inspect_release(name, params['version'])
66
+ end
67
+
64
68
  release = @release_manager.find_by_name(name)
65
69
 
66
70
  result = { }
@@ -101,6 +105,44 @@ module Bosh::Director
101
105
  task = @release_manager.delete_release(current_user, release, options)
102
106
  redirect "/tasks/#{task.id}"
103
107
  end
108
+
109
+ private
110
+
111
+ def inspect_release(name, version)
112
+ release = @release_manager.find_by_name(name)
113
+ release_version = @release_manager.find_version(release, version)
114
+
115
+ result = { }
116
+
117
+ result['jobs'] = release_version.templates.sort_by { |t| t.name }.map do |template|
118
+ {
119
+ 'name' => template.name,
120
+ 'blobstore_id' => template.blobstore_id,
121
+ 'sha1' => template.sha1,
122
+ 'fingerprint' => template.fingerprint.to_s,
123
+ }
124
+ end
125
+
126
+ result['packages'] = release_version.packages.sort_by { |p| p.name }.map do |package|
127
+ {
128
+ 'name' => package.name,
129
+ 'blobstore_id' => package.blobstore_id,
130
+ 'sha1' => package.sha1,
131
+ 'fingerprint' => package.fingerprint.to_s,
132
+ 'compiled_packages' => package.compiled_packages.sort_by { |cp| cp.stemcell }.map do |compiled|
133
+ {
134
+ 'stemcell' => "#{compiled.stemcell.name}/#{compiled.stemcell.version}",
135
+ 'sha1' => compiled.sha1,
136
+ 'blobstore_id' => compiled.blobstore_id,
137
+ }
138
+ end
139
+ }
140
+ end
141
+
142
+ content_type(:json)
143
+ json_encode(result)
144
+ end
145
+
104
146
  end
105
147
  end
106
148
  end
@@ -16,20 +16,30 @@ module Bosh::Director
16
16
  path = File.join(@download_dir, 'compiled_packages')
17
17
  FileUtils.mkpath(path)
18
18
 
19
- @compiled_packages_group.compiled_packages.each do |compiled_package|
20
- blobstore_id = compiled_package.blobstore_id
21
- File.open(File.join(path, "#{compiled_package.package.name}.tgz"), 'w') do |f|
22
- @blobstore_client.get(blobstore_id, f, sha1: compiled_package.sha1)
19
+ compiled_packages = @compiled_packages_group.compiled_packages
20
+ event_log.begin_stage("copying packages", compiled_packages.count)
21
+
22
+ compiled_packages.each do |compiled_package|
23
+ desc = "#{compiled_package.package.name}/#{compiled_package.package.version}"
24
+ event_log.track(desc) do
25
+ blobstore_id = compiled_package.blobstore_id
26
+ File.open(File.join(path, "#{compiled_package.package.name}.tgz"), 'w') do |f|
27
+ @blobstore_client.get(blobstore_id, f, sha1: compiled_package.sha1)
28
+ end
23
29
  end
24
30
  end
25
31
 
26
32
  path = File.join(@download_dir, 'jobs')
27
33
  FileUtils.mkpath(path)
28
34
 
35
+ event_log.begin_stage("copying jobs", @templates.count)
29
36
  @templates.each do |template|
30
- blobstore_id = template.blobstore_id
31
- File.open(File.join(path, "#{template.name}.tgz"), 'w') do |f|
32
- @blobstore_client.get(blobstore_id, f, sha1: template.sha1)
37
+ desc = "#{template.name}/#{template.version}"
38
+ event_log.track(desc) do
39
+ blobstore_id = template.blobstore_id
40
+ File.open(File.join(path, "#{template.name}.tgz"), 'w') do |f|
41
+ @blobstore_client.get(blobstore_id, f, sha1: template.sha1)
42
+ end
33
43
  end
34
44
  end
35
45
 
@@ -39,5 +49,10 @@ module Bosh::Director
39
49
  def cleanup
40
50
  FileUtils.rm_rf(@download_dir)
41
51
  end
52
+
53
+ def event_log
54
+ @event_log ||= Config.event_log
55
+ end
56
+
42
57
  end
43
58
  end
@@ -51,7 +51,15 @@ module Bosh::Director
51
51
  end
52
52
 
53
53
  def write(dest_path)
54
- File.open(dest_path, 'w') { |f| f.write(YAML.dump(generate_manifest)) }
54
+ manifest = generate_manifest
55
+ manifest_yaml = YAML.dump(manifest)
56
+ logger.debug("release.MF contents of #{manifest['name']}/#{manifest['version']} compiled release tarball:\n " + manifest_yaml)
57
+ File.open(dest_path, 'w') { |f| f.write(manifest_yaml) }
55
58
  end
59
+
60
+ def logger
61
+ @logger ||= Config.logger
62
+ end
63
+
56
64
  end
57
65
  end
@@ -36,7 +36,11 @@ module Bosh::Director
36
36
  :nats_uri,
37
37
  )
38
38
 
39
- attr_reader :db_config, :redis_logger_level
39
+ attr_reader(
40
+ :db_config,
41
+ :redis_logger_level,
42
+ :ignore_missing_gateway
43
+ )
40
44
 
41
45
  def clear
42
46
  self.instance_variables.each do |ivar|
@@ -141,6 +145,7 @@ module Bosh::Director
141
145
  @enable_snapshots = config.fetch('snapshots', {}).fetch('enabled', false)
142
146
 
143
147
  @trusted_certs = config['trusted_certs'] || ''
148
+ @ignore_missing_gateway = config['ignore_missing_gateway']
144
149
 
145
150
  Bosh::Clouds::Config.configure(self)
146
151
 
@@ -171,7 +176,12 @@ module Bosh::Director
171
176
  db_config = db_config.merge(connection_options)
172
177
 
173
178
  db = Sequel.connect(db_config)
174
- db.extension :connection_validator
179
+
180
+ Bosh::Common.retryable(sleep: 0.5, tries: 20, on: [Exception]) do
181
+ db.extension :connection_validator
182
+ true
183
+ end
184
+
175
185
  db.pool.connection_validation_timeout = -1
176
186
  if logger
177
187
  db.logger = logger
@@ -43,7 +43,8 @@ module Bosh::Director
43
43
  network_id = @range.network(:Objectify => true)
44
44
  broadcast = @range.broadcast(:Objectify => true)
45
45
 
46
- gateway_property = safe_property(subnet_spec, "gateway", class: String)
46
+ ignore_missing_gateway = Bosh::Director::Config.ignore_missing_gateway
47
+ gateway_property = safe_property(subnet_spec, "gateway", class: String, optional: ignore_missing_gateway)
47
48
  if gateway_property
48
49
  @gateway = NetAddr::CIDR.create(gateway_property)
49
50
  unless @gateway.size == 1
@@ -0,0 +1,20 @@
1
+ module Bosh::Director
2
+ module DeploymentPlan
3
+ class SkipDrain
4
+ def initialize(param)
5
+ @jobs = []
6
+ @all = false
7
+
8
+ if param == '*'
9
+ @all = true
10
+ elsif param.is_a?(String) && !param.empty?
11
+ @jobs = param.split(',')
12
+ end
13
+ end
14
+
15
+ def for_job(job_name)
16
+ @all || @jobs.include?(job_name)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -45,6 +45,9 @@ module Bosh::Director
45
45
  # @return [Boolean] Indicates whether VMs should be recreated
46
46
  attr_reader :recreate
47
47
 
48
+ # @return [Boolean] Indicates whether VMs should be drained
49
+ attr_reader :skip_drain
50
+
48
51
  def initialize(attrs, manifest_text, cloud_config, deployment_model, options = {})
49
52
  @name = attrs.fetch(:name)
50
53
  @properties = attrs.fetch(:properties)
@@ -67,6 +70,7 @@ module Bosh::Director
67
70
  :class => Hash, :default => {})
68
71
 
69
72
  @recreate = !!options['recreate']
73
+ @skip_drain = SkipDrain.new(options['skip_drain'])
70
74
  end
71
75
 
72
76
  def_delegators :@cloud_planner, :add_network, :networks, :network,
@@ -84,6 +88,10 @@ module Bosh::Director
84
88
  @model.vms
85
89
  end
86
90
 
91
+ def skip_drain_for_job?(name)
92
+ @skip_drain.nil? ? false : @skip_drain.for_job(name)
93
+ end
94
+
87
95
  # Adds a release by name
88
96
  # @param [Bosh::Director::DeploymentPlan::ReleaseVersion] release
89
97
  def add_release(release)
@@ -56,6 +56,32 @@ module Bosh
56
56
  assemble_without_vm_binding(attrs, deployment_manifest, cloud_manifest, deployment_model, cloud_config, options)
57
57
  end
58
58
 
59
+ def self.validate_packages(planner, options)
60
+ release_manager = Bosh::Director::Api::ReleaseManager.new
61
+ planner.jobs.each { |job|
62
+ job.templates.each{ |template|
63
+ release_model = release_manager.find_by_name(template.release.name)
64
+ template.package_models.each{ |package|
65
+
66
+ release_version_model = release_manager.find_version(release_model, template.release.version)
67
+ packages_list = release_version_model.transitive_dependencies(package)
68
+ packages_list << package
69
+
70
+ packages_list.each { |needed_package|
71
+ if needed_package.sha1.nil? || needed_package.blobstore_id.nil?
72
+ compiled_packages_list = Bosh::Director::Models::CompiledPackage[:package_id => needed_package.id, :stemcell_id => job.resource_pool.stemcell.model.id]
73
+ if compiled_packages_list.nil?
74
+ msg = "Can't #{options[:context]} `#{release_version_model.release.name}/#{release_version_model.version}': it is not " +
75
+ "compiled for `#{job.resource_pool.stemcell.model.desc}' and no source package is available"
76
+ raise PackageMissingSourceCode, msg
77
+ end
78
+ end
79
+ }
80
+ }
81
+ }
82
+ }
83
+ end
84
+
59
85
  private
60
86
 
61
87
  def deployment_name(manifest_hash)
@@ -66,11 +92,12 @@ module Bosh
66
92
  def assemble_without_vm_binding(attrs, deployment_manifest, cloud_manifest, deployment_model, cloud_config, options)
67
93
  plan_options = {
68
94
  'recreate' => !!options['recreate'],
95
+ 'skip_drain' => options['skip_drain'],
69
96
  'job_states' => options['job_states'] || {},
70
97
  'job_rename' => options['job_rename'] || {}
71
98
  }
72
99
  @logger.info('Creating deployment plan')
73
- @logger.info("Deployment plan options: #{plan_options.pretty_inspect}")
100
+ @logger.info("Deployment plan options: #{plan_options}")
74
101
 
75
102
  deployment = Planner.new(attrs, deployment_manifest, cloud_config, deployment_model, plan_options)
76
103
  deployment = CloudManifestParser.new(deployment, @logger).parse(cloud_manifest)
@@ -94,6 +121,8 @@ module Bosh
94
121
 
95
122
  run_prepare_step(assembler)
96
123
 
124
+ self.class.validate_packages(planner, {:context => 'deploy'})
125
+
97
126
  DeploymentPlan::Steps::PackageCompileStep.new(
98
127
  planner,
99
128
  cloud,
@@ -30,3 +30,4 @@ require 'bosh/director/deployment_plan/assembler'
30
30
  require 'bosh/director/deployment_plan/planner_factory'
31
31
  require 'bosh/director/deployment_plan/manifest_migrator'
32
32
  require 'bosh/director/deployment_plan/deployment_repo'
33
+ require 'bosh/director/deployment_plan/options/skip_drain'
@@ -26,8 +26,8 @@ module Bosh::Director
26
26
 
27
27
  begin
28
28
  event_log_stage.advance_and_track("#{@job.name}/#{instance.index}") do
29
- start_errand_result = agent.start_errand
30
- @agent_task_id = start_errand_result['agent_task_id']
29
+ run_errand_result = agent.run_errand
30
+ @agent_task_id = run_errand_result['agent_task_id']
31
31
  agent_task_result = agent.wait_for_task(agent_task_id, &blk)
32
32
  end
33
33
  rescue TaskCancelled => e
@@ -73,6 +73,7 @@ module Bosh::Director
73
73
  ReleaseVersionInUse = err(30008)
74
74
  ReleaseDeleteFailed = err(30009)
75
75
  ReleaseVersionInvalid = err(30010)
76
+ ReleaseNotMatchingManifest = err(30011)
76
77
 
77
78
  ValidationInvalidType = err(40000)
78
79
  ValidationMissingField = err(40001)
@@ -86,6 +87,7 @@ module Bosh::Director
86
87
  StemcellInUse = err(50004)
87
88
 
88
89
  PackageInvalidArchive = err(60000)
90
+ PackageMissingSourceCode = err(60001)
89
91
 
90
92
  # Models
91
93
  DeploymentNotFound = err(70000, NOT_FOUND)
@@ -213,6 +215,7 @@ module Bosh::Director
213
215
 
214
216
  PackageCompilationNetworkNotReserved = err(430001)
215
217
  PackageCompilationNotEnoughWorkersForReuse = err(430002)
218
+ PackageCompilationNotFound = err(430003)
216
219
 
217
220
  BadManifest = err(440001)
218
221
 
@@ -1,14 +1,27 @@
1
1
  module Bosh::Director
2
2
  class InstanceUpdater::Stopper
3
- def initialize(instance, agent_client, target_state, config, logger)
3
+ def initialize(instance, agent_client, target_state, skip_drain, config, logger)
4
4
  @instance = instance
5
5
  @agent_client = agent_client
6
6
  @target_state = target_state
7
+ @skip_drain = skip_drain
7
8
  @config = config
8
9
  @logger = logger
9
10
  end
10
11
 
11
12
  def stop
13
+ if @skip_drain
14
+ @logger.info("Skipping drain for '#{@instance}'")
15
+ else
16
+ perform_drain
17
+ end
18
+
19
+ @agent_client.stop
20
+ end
21
+
22
+ private
23
+
24
+ def perform_drain
12
25
  drain_type = shutting_down? ? 'shutdown' : 'update'
13
26
 
14
27
  # Apply spec might change after shutdown drain (unlike update drain)
@@ -21,12 +34,8 @@ module Bosh::Director
21
34
  else
22
35
  wait_for_dynamic_drain(drain_time)
23
36
  end
24
-
25
- @agent_client.stop
26
37
  end
27
38
 
28
- private
29
-
30
39
  def shutting_down?
31
40
  @instance.resource_pool_changed? ||
32
41
  @instance.persistent_disk_changed? ||
@@ -143,7 +143,8 @@ module Bosh::Director
143
143
  end
144
144
 
145
145
  def stop
146
- stopper = Stopper.new(@instance, agent, @target_state, Config, @logger)
146
+ skip_drain = @deployment_plan.skip_drain_for_job?(@job.name)
147
+ stopper = Stopper.new(@instance, agent, @target_state, skip_drain, Config, @logger)
147
148
  stopper.stop
148
149
  end
149
150
 
@@ -132,12 +132,13 @@ module Bosh::Director
132
132
  "(#{compiled_package.blobstore_id}) " +
133
133
  "#{package.name}/#{package.version} " +
134
134
  "for #{stemcell.name}/#{stemcell.version}")
135
- delete_blobstore_id(compiled_package.blobstore_id) do
135
+
136
+ if delete_blobstore_id(compiled_package.blobstore_id)
136
137
  compiled_package.destroy
137
138
  end
138
139
  end
139
140
 
140
- delete_blobstore_id(package.blobstore_id) do
141
+ if delete_blobstore_id(package.blobstore_id, true)
141
142
  package.remove_all_release_versions
142
143
  package.destroy
143
144
  end
@@ -146,7 +147,7 @@ module Bosh::Director
146
147
  def delete_template(template)
147
148
  logger.info("Deleting template: #{template.name}/#{template.version}")
148
149
 
149
- delete_blobstore_id(template.blobstore_id) do
150
+ if delete_blobstore_id(template.blobstore_id)
150
151
  template.remove_all_release_versions
151
152
  template.destroy
152
153
  end
@@ -201,17 +202,21 @@ module Bosh::Director
201
202
  "/release/#{@name}"
202
203
  end
203
204
 
204
- def delete_blobstore_id(blobstore_id)
205
+ def delete_blobstore_id(blobstore_id, nil_id_allowed = false)
206
+ if blobstore_id.nil? && nil_id_allowed
207
+ return true
208
+ end
209
+
205
210
  deleted = false
206
211
  begin
207
212
  @blobstore.delete(blobstore_id)
208
213
  deleted = true
209
214
  rescue Exception => e
210
- logger.warn("Could not delete from blobstore: #{e}\n " +
211
- e.backtrace.join("\n"))
215
+ logger.warn("Could not delete from blobstore: #{e}\n " + e.backtrace.join("\n"))
212
216
  @errors << e
213
217
  end
214
- yield if deleted || @force
218
+
219
+ return deleted || @force
215
220
  end
216
221
 
217
222
  end
@@ -10,10 +10,6 @@ module Bosh::Director
10
10
 
11
11
  @queue = :normal
12
12
 
13
- @stemcell
14
- @targeted_deployment
15
- @release_version
16
-
17
13
  def self.job_type
18
14
  :export_release
19
15
  end
@@ -29,7 +25,24 @@ module Bosh::Director
29
25
  # @return [void]
30
26
  def perform
31
27
  logger.info("Exporting release: #{@release_name}/#{@release_version} for #{@stemcell_os}/#{@stemcell_version}")
32
- validate_and_prepare
28
+
29
+ stemcell_manager = Bosh::Director::Api::StemcellManager.new
30
+ @stemcell = stemcell_manager.find_by_os_and_version(@stemcell_os, @stemcell_version)
31
+
32
+ logger.info "Will compile with stemcell: #{@stemcell.desc}"
33
+
34
+ deployment_manager = Bosh::Director::Api::DeploymentManager.new
35
+ @targeted_deployment = deployment_manager.find_by_name(@deployment_name)
36
+ @deployment_manifest = Psych.load(@targeted_deployment.manifest)
37
+
38
+ release_manager = Bosh::Director::Api::ReleaseManager.new
39
+ release = release_manager.find_by_name(@release_name)
40
+ @release_version_model = release_manager.find_version(release, @release_version)
41
+
42
+ unless deployment_manifest_has_release?
43
+ raise ReleaseNotMatchingManifest, "Release #{@release_name}/#{@release_version} not found in deployment #{@deployment_name} manifest"
44
+ end
45
+
33
46
  lock_timeout = 15 * 60 # 15 minutes
34
47
 
35
48
  with_deployment_lock(@deployment_name, :timeout => lock_timeout) do
@@ -37,6 +50,7 @@ module Bosh::Director
37
50
  with_stemcell_lock(@stemcell.name, @stemcell.version, :timeout => lock_timeout) do
38
51
 
39
52
  planner = create_planner
53
+ DeploymentPlan::PlannerFactory.validate_packages(planner, {:context => 'export'})
40
54
  package_compile_step = DeploymentPlan::Steps::PackageCompileStep.new(
41
55
  planner,
42
56
  Config.cloud, # CPI
@@ -55,27 +69,21 @@ module Bosh::Director
55
69
  "Exported release: #{@release_name}/#{@release_version} for #{@stemcell_os}/#{@stemcell_version}"
56
70
  end
57
71
 
58
- def validate_and_prepare
59
- stemcell_manager = Bosh::Director::Api::StemcellManager.new
60
- @stemcell = stemcell_manager.find_by_os_and_version(@stemcell_os, @stemcell_version)
61
-
62
- logger.info "Will compile with stemcell: #{@stemcell.desc}"
63
-
64
- deployment_manager = Bosh::Director::Api::DeploymentManager.new
65
- @targeted_deployment = deployment_manager.find_by_name(@deployment_name)
66
-
67
- release_manager = Bosh::Director::Api::ReleaseManager.new
68
- release = release_manager.find_by_name(@release_name)
69
- @release_version = release_manager.find_version(release, @release_version)
72
+ def deployment_manifest_has_release?
73
+ @deployment_manifest["releases"].each do |release|
74
+ if (release["name"] == @release_name) && (release["version"].to_s == @release_version.to_s)
75
+ return true
76
+ end
77
+ end
78
+ false
70
79
  end
71
80
 
72
81
  def create_planner
73
- modified_deployment_manifest = Psych.load(@targeted_deployment.manifest)
74
82
  cloud_config_model = @targeted_deployment.cloud_config
75
83
 
76
84
  planner_factory = DeploymentPlan::PlannerFactory.create(Config.event_log, Config.logger)
77
85
  planner = planner_factory.planner_without_vm_binding(
78
- modified_deployment_manifest,
86
+ @deployment_manifest,
79
87
  cloud_config_model,
80
88
  {}
81
89
  )
@@ -101,8 +109,8 @@ module Bosh::Director
101
109
 
102
110
  blobstore_client = Bosh::Director::App.instance.blobstores.blobstore
103
111
 
104
- compiled_packages_group = CompiledPackageGroup.new(@release_version, @stemcell)
105
- templates = @release_version.templates.map
112
+ compiled_packages_group = CompiledPackageGroup.new(@release_version_model, @stemcell)
113
+ templates = @release_version_model.templates.map
106
114
 
107
115
  compiled_release_downloader = CompiledReleaseDownloader.new(compiled_packages_group, templates, blobstore_client)
108
116
  download_dir = compiled_release_downloader.download
@@ -132,14 +140,14 @@ module Bosh::Director
132
140
  "release" => @release_name,
133
141
  "instances" => 1,
134
142
  "resource_pool" => fake_resource_pool_manifest['name'],
135
- "templates" => @release_version.templates.map do |template|
143
+ "templates" => @release_version_model.templates.map do |template|
136
144
  { "name" => template.name, "release" => @release_name }
137
145
  end,
138
146
  "networks" => [ "name" => network_name ],
139
147
  }
140
148
 
141
149
  fake_job = DeploymentPlan::Job.parse(planner, fake_job_spec_for_compiling, Config.event_log, Config.logger)
142
- @release_version.packages.each { |package| fake_job.packages[package.name] = package }
150
+ @release_version_model.packages.each { |package| fake_job.packages[package.name] = package }
143
151
  fake_job.resource_pool.stemcell.bind_model
144
152
  fake_job.release.bind_model
145
153
  fake_job.templates.each { |template| template.bind_models }
@@ -33,13 +33,6 @@ module Bosh::Director
33
33
 
34
34
  @rebase = !!options['rebase']
35
35
  @skip_if_exists = !!options['skip_if_exists']
36
- @compiled_release = !!options['compiled']
37
-
38
- if @compiled_release
39
- @packages_folder = "compiled_packages"
40
- else
41
- @packages_folder = "packages"
42
- end
43
36
 
44
37
  @manifest = nil
45
38
  @name = nil
@@ -66,10 +59,6 @@ module Bosh::Director
66
59
  process_release(release_dir)
67
60
  }
68
61
 
69
- if @rebase && @packages_unchanged && @jobs_unchanged
70
- raise DirectorError, "Rebase is attempted without any job or package changes"
71
- end
72
-
73
62
  "Created release `#{@name}/#{@version}'"
74
63
 
75
64
  rescue Exception => e
@@ -95,6 +84,7 @@ module Bosh::Director
95
84
  logger.error("Failed to extract release archive '#{@release_path}' into dir '#{release_dir}', " +
96
85
  "tar returned #{result.exit_status}, " +
97
86
  "output: #{result.output}")
87
+ FileUtils.rm_rf(release_dir)
98
88
  raise ReleaseInvalidArchive, "Extracting release archive failed. Check task debug log for details."
99
89
  end
100
90
 
@@ -110,6 +100,15 @@ module Bosh::Director
110
100
  end
111
101
 
112
102
  @manifest = Psych.load_file(manifest_file)
103
+
104
+ #handle compiled_release case
105
+ @compiled_release = !!@manifest["compiled_packages"]
106
+ if @compiled_release
107
+ @packages_folder = "compiled_packages"
108
+ else
109
+ @packages_folder = "packages"
110
+ end
111
+
113
112
  normalize_manifest
114
113
 
115
114
  @name = @manifest["name"]
@@ -253,69 +252,134 @@ module Bosh::Director
253
252
  end
254
253
  end
255
254
 
256
- create_packages(new_packages, release_dir)
257
- use_existing_packages(existing_packages)
255
+ package_stemcell_hashes1 = create_packages(new_packages, release_dir)
256
+ package_stemcell_hashes2 = use_existing_packages(existing_packages)
257
+ consolidated_package_stemcell_hashes = Array(package_stemcell_hashes1) | Array(package_stemcell_hashes2)
258
+
259
+ create_compiled_packages(consolidated_package_stemcell_hashes, release_dir)
260
+ end
261
+
262
+ # Points release DB model to existing packages described by given metadata
263
+ # @param [Array<Array>] packages Existing packages metadata
264
+ def use_existing_packages(packages)
265
+ return if packages.empty?
266
+
267
+ package_stemcell_hashes = []
268
+
269
+ single_step_stage("Processing #{packages.size} existing package#{"s" if packages.size > 1}") do
270
+ packages.each do |package, package_meta|
271
+ package_desc = "#{package.name}/#{package.version}"
272
+ logger.info("Using existing package `#{package_desc}'")
273
+ register_package(package)
274
+
275
+ if @compiled_release
276
+ stemcells = stemcells_used_by_package(package_meta)
277
+ stemcells.each do |stemcell|
278
+ hash = { "package" => package, "stemcell" => stemcell}
279
+ package_stemcell_hashes << hash
280
+ end
281
+ end
282
+ end
283
+ end
284
+
285
+ package_stemcell_hashes
258
286
  end
259
287
 
260
288
  # Creates packages using provided metadata
261
289
  # @param [Array<Hash>] packages Packages metadata
262
290
  # @param [String] release_dir local path to the unpacked release
263
- # @return [void]
264
- def create_packages(packages, release_dir)
265
- if packages.empty?
291
+ # @return [Array<Hash>] package & stemcell
292
+ def create_packages(package_metas, release_dir)
293
+ if package_metas.empty?
266
294
  @packages_unchanged = true
267
295
  return
268
296
  end
269
297
 
270
- event_log.begin_stage("Creating new packages", packages.size)
271
- packages.each do |package_meta|
298
+ package_stemcell_hashes = []
299
+ event_log.begin_stage("Creating new packages", package_metas.size)
300
+
301
+ package = package_metas.each do |package_meta|
272
302
  package_desc = "#{package_meta["name"]}/#{package_meta["version"]}"
273
303
  event_log.track(package_desc) do
274
304
  logger.info("Creating new package `#{package_desc}'")
305
+ package = create_package(package_meta, release_dir)
306
+ register_package(package)
307
+ package
308
+ end
275
309
 
276
- if @compiled_release
277
- package = create_package_for_compiled_release(package_meta, release_dir)
278
- else
279
- package = create_package(package_meta, release_dir)
310
+ if @compiled_release
311
+ stemcells = stemcells_used_by_package(package_meta)
312
+ stemcells.each do |stemcell|
313
+ hash = { "package" => package, "stemcell" => stemcell}
314
+ package_stemcell_hashes << hash
280
315
  end
281
-
282
- register_package(package)
283
316
  end
284
317
  end
318
+
319
+ package_stemcell_hashes
285
320
  end
286
321
 
287
- # Points release DB model to existing packages described by given metadata
288
- # @param [Array<Array>] packages Existing packages metadata
289
- def use_existing_packages(packages)
290
- return if packages.empty?
322
+ def create_compiled_packages(all_compiled_packages, release_dir)
323
+ if all_compiled_packages.nil?
324
+ return
325
+ end
291
326
 
292
- single_step_stage("Processing #{packages.size} existing package#{"s" if packages.size > 1}") do
293
- packages.each do |package, _|
294
- package_desc = "#{package.name}/#{package.version}"
295
- logger.info("Using existing package `#{package_desc}'")
296
- register_package(package)
327
+ event_log.begin_stage('Creating new compiled packages', all_compiled_packages.size)
328
+
329
+ all_compiled_packages.each do |compiled_package_spec|
330
+ package = compiled_package_spec['package']
331
+ stemcell = compiled_package_spec['stemcell']
332
+
333
+ existing_compiled_package = Models::CompiledPackage.where(
334
+ :package_id => package.id,
335
+ :stemcell_id => stemcell.id)
336
+
337
+ if existing_compiled_package.empty?
338
+ package_desc = "#{package.name}/#{package.version} for #{stemcell.name}/#{stemcell.version}"
339
+ event_log.track(package_desc) do
340
+ create_compiled_package(package, stemcell, release_dir)
341
+ end
297
342
  end
298
343
  end
299
344
  end
300
345
 
301
- def create_package_for_compiled_release(package_meta, release_dir)
302
- name, version = package_meta["name"], package_meta["version"]
303
- desc = "package `#{name}/#{version}'"
346
+ def stemcells_used_by_package(package_meta)
347
+ if package_meta['stemcell'].nil?
348
+ raise 'stemcell informatiom(operating system/version) should be listed for each package of a compiled tarball'
349
+ end
304
350
 
305
- package_attrs = {
306
- :release => @release_model,
307
- :name => name,
308
- :sha1 => nil,
309
- :blobstore_id => nil,
310
- :fingerprint => package_meta["fingerprint"],
311
- :version => version
312
- }
351
+ values = package_meta['stemcell'].split('/', 2)
352
+ operating_system = values[0]
353
+ stemcell_version = values[1]
354
+ unless operating_system && stemcell_version
355
+ raise 'stemcell informatiom(operating system/version) should be listed for each package of a compiled tarball'
356
+ end
313
357
 
314
- package = Models::Package.new(package_attrs)
315
- package.dependency_set = package_meta["dependencies"]
358
+ stemcells = Models::Stemcell.where(:operating_system => operating_system, :version => stemcell_version)
359
+ if stemcells.empty?
360
+ raise "No stemcells matching OS #{operating_system} version #{stemcell_version}"
361
+ end
316
362
 
317
- logger.info("Creating #{desc} from provided bits")
318
- package.save
363
+ stemcells
364
+ end
365
+
366
+ def create_compiled_package(package, stemcell, release_dir)
367
+ tgz = File.join(release_dir, 'compiled_packages', "#{package.name}.tgz")
368
+ validate_tgz(tgz, "#{package.name}.tgz")
369
+
370
+ compiled_package = Models::CompiledPackage.new
371
+
372
+ compiled_package.blobstore_id = BlobUtil.create_blob(tgz)
373
+ compiled_package.sha1 = Digest::SHA1.file(tgz).hexdigest
374
+
375
+ transitive_dependencies = @release_version_model.transitive_dependencies(package)
376
+ compiled_package.dependency_key = Models::CompiledPackage.create_dependency_key(transitive_dependencies)
377
+
378
+ compiled_package.build = Models::CompiledPackage.generate_build_number(package, stemcell)
379
+ compiled_package.package_id = package.id
380
+ compiled_package.stemcell_id = stemcell.id
381
+
382
+ compiled_package.save
319
383
  end
320
384
 
321
385
  # Creates package in DB according to given metadata
@@ -323,43 +387,48 @@ module Bosh::Director
323
387
  # @param [String] release_dir local path to the unpacked release
324
388
  # @return [void]
325
389
  def create_package(package_meta, release_dir)
326
- name, version = package_meta["name"], package_meta["version"]
390
+ name, version = package_meta['name'], package_meta['version']
327
391
 
328
392
  package_attrs = {
329
- :release => @release_model,
330
- :name => name,
331
- :sha1 => package_meta["sha1"],
332
- :fingerprint => package_meta["fingerprint"],
333
- :version => version
393
+ :release => @release_model,
394
+ :name => name,
395
+ :sha1 => @compiled_release ? nil : package_meta['sha1'],
396
+ :blobstore_id => nil,
397
+ :fingerprint => package_meta['fingerprint'],
398
+ :version => version
334
399
  }
335
400
 
336
401
  package = Models::Package.new(package_attrs)
337
- package.dependency_set = package_meta["dependencies"]
402
+ package.dependency_set = package_meta['dependencies']
338
403
 
339
- existing_blob = package_meta["blobstore_id"]
340
- desc = "package `#{name}/#{version}'"
404
+ unless @compiled_release
405
+ existing_blob = package_meta['blobstore_id']
406
+ desc = "package '#{name}/#{version}'"
341
407
 
342
- if existing_blob
343
- logger.info("Creating #{desc} from existing blob #{existing_blob}")
344
- package.blobstore_id = BlobUtil.copy_blob(existing_blob)
345
- else
346
- logger.info("Creating #{desc} from provided bits")
347
-
348
- package_tgz = File.join(release_dir, "packages", "#{name}.tgz")
349
- result = Bosh::Exec.sh("tar -tzf #{package_tgz} 2>&1", :on_error => :return)
350
- if result.failed?
351
- logger.error("Extracting #{desc} archive failed, " +
352
- "tar returned #{result.exit_status}, " +
353
- "output: #{result.output}")
354
- raise PackageInvalidArchive, "Extracting #{desc} archive failed. Check task debug log for details."
355
- end
408
+ if existing_blob
409
+ logger.info("Creating #{desc} from existing blob #{existing_blob}")
410
+ package.blobstore_id = BlobUtil.copy_blob(existing_blob)
411
+
412
+ else
413
+ logger.info("Creating #{desc} from provided bits")
356
414
 
357
- package.blobstore_id = BlobUtil.create_blob(package_tgz)
415
+ package_tgz = File.join(release_dir, 'packages', "#{name}.tgz")
416
+ validate_tgz(package_tgz, desc)
417
+ package.blobstore_id = BlobUtil.create_blob(package_tgz)
418
+ end
358
419
  end
359
420
 
360
421
  package.save
361
422
  end
362
423
 
424
+ def validate_tgz(tgz, desc)
425
+ result = Bosh::Exec.sh("tar -tzf #{tgz} 2>&1", :on_error => :return)
426
+ if result.failed?
427
+ logger.error("Extracting #{desc} archive failed, tar returned #{result.exit_status}, output: #{result.output}")
428
+ raise PackageInvalidArchive, "Extracting #{desc} archive failed. Check task debug log for details."
429
+ end
430
+ end
431
+
363
432
  # Marks package model as used by release version model
364
433
  # @param [Models::Package] package Package model
365
434
  # @return [void]
@@ -18,6 +18,10 @@ module Bosh::Director::Models
18
18
  end
19
19
 
20
20
  def validate
21
+ if !sha1.nil? || !blobstore_id.nil?
22
+ validates_presence [:sha1, :blobstore_id]
23
+ end
24
+
21
25
  validates_presence [:release_id, :name, :version]
22
26
  validates_unique [:release_id, :name, :version]
23
27
  validates_format VALID_ID, [:name, :version]
@@ -1,5 +1,5 @@
1
1
  module Bosh
2
2
  module Director
3
- VERSION = '1.3022.0'
3
+ VERSION = '1.3048.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.3022.0
4
+ version: 1.3048.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - VMware
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-23 00:00:00.000000000 Z
11
+ date: 2015-08-18 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.3022.0
33
+ version: 1.3048.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.3022.0
40
+ version: 1.3048.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.3022.0
47
+ version: 1.3048.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.3022.0
54
+ version: 1.3048.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.3022.0
61
+ version: 1.3048.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.3022.0
68
+ version: 1.3048.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.3022.0
75
+ version: 1.3048.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.3022.0
82
+ version: 1.3048.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: bosh-template
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 1.3022.0
89
+ version: 1.3048.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.3022.0
96
+ version: 1.3048.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: bosh_cpi
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 1.3022.0
103
+ version: 1.3048.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.3022.0
110
+ version: 1.3048.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: bosh_openstack_cpi
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 1.3022.0
117
+ version: 1.3048.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.3022.0
124
+ version: 1.3048.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: bosh_aws_cpi
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 1.3022.0
131
+ version: 1.3048.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.3022.0
138
+ version: 1.3048.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: bosh_vsphere_cpi
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 1.3022.0
145
+ version: 1.3048.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.3022.0
152
+ version: 1.3048.0
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: bosh_vcloud_cpi
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -572,7 +572,7 @@ dependencies:
572
572
  version: '0'
573
573
  description: |-
574
574
  BOSH Director
575
- 6073a7
575
+ e2c11a
576
576
  email: support@cloudfoundry.com
577
577
  executables:
578
578
  - bosh-director
@@ -723,6 +723,7 @@ files:
723
723
  - lib/bosh/director/deployment_plan/network.rb
724
724
  - lib/bosh/director/deployment_plan/network_subnet.rb
725
725
  - lib/bosh/director/deployment_plan/notifier.rb
726
+ - lib/bosh/director/deployment_plan/options/skip_drain.rb
726
727
  - lib/bosh/director/deployment_plan/planner.rb
727
728
  - lib/bosh/director/deployment_plan/planner_factory.rb
728
729
  - lib/bosh/director/deployment_plan/release_version.rb