bosh-director 1.2957.0 → 1.2962.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bosh/director.rb +0 -1
  3. data/lib/bosh/director/api/cloud_config_manager.rb +9 -0
  4. data/lib/bosh/director/api/controllers/deployments_controller.rb +12 -4
  5. data/lib/bosh/director/deployment_plan.rb +4 -2
  6. data/lib/bosh/director/deployment_plan/assembler.rb +6 -62
  7. data/lib/bosh/director/deployment_plan/cloud_manifest_parser.rb +77 -0
  8. data/lib/bosh/director/deployment_plan/compilation_config.rb +12 -12
  9. data/lib/bosh/director/deployment_plan/deployment_repo.rb +28 -0
  10. data/lib/bosh/director/deployment_plan/deployment_spec_parser.rb +5 -74
  11. data/lib/bosh/director/deployment_plan/dynamic_network.rb +2 -2
  12. data/lib/bosh/director/deployment_plan/manifest_migrator.rb +53 -0
  13. data/lib/bosh/director/deployment_plan/manual_network.rb +1 -1
  14. data/lib/bosh/director/deployment_plan/network_subnet.rb +3 -4
  15. data/lib/bosh/director/deployment_plan/notifier.rb +5 -5
  16. data/lib/bosh/director/deployment_plan/planner.rb +96 -122
  17. data/lib/bosh/director/deployment_plan/planner_factory.rb +148 -0
  18. data/lib/bosh/director/deployment_plan/release_version.rb +6 -7
  19. data/lib/bosh/director/deployment_plan/resource_pool.rb +6 -6
  20. data/lib/bosh/director/deployment_plan/steps/package_compile_step.rb +5 -5
  21. data/lib/bosh/director/deployment_plan/steps/update_step.rb +59 -11
  22. data/lib/bosh/director/deployment_plan/vip_network.rb +1 -1
  23. data/lib/bosh/director/errand.rb +0 -1
  24. data/lib/bosh/director/errand/job_manager.rb +5 -0
  25. data/lib/bosh/director/errors.rb +2 -0
  26. data/lib/bosh/director/jobs/fetch_logs.rb +1 -1
  27. data/lib/bosh/director/jobs/run_errand.rb +31 -30
  28. data/lib/bosh/director/jobs/update_deployment.rb +32 -50
  29. data/lib/bosh/director/models/deployment.rb +0 -1
  30. data/lib/bosh/director/version.rb +1 -1
  31. metadata +25 -23
  32. data/lib/bosh/director/deployment_plan/steps/prepare_step.rb +0 -56
  33. data/lib/bosh/director/errand/deployment_preparer.rb +0 -26
@@ -0,0 +1,53 @@
1
+ module Bosh
2
+ module Director
3
+ module DeploymentPlan
4
+ class ManifestMigrator
5
+ def migrate(manifest_hash, cloud_config)
6
+ migrate_releases(manifest_hash)
7
+
8
+ if cloud_config.nil?
9
+ cloud_manifest = cloud_manifest_from_deployment_manifest(manifest_hash)
10
+ else
11
+ verify_deployment_without_cloud_config(manifest_hash)
12
+ cloud_manifest = cloud_config.manifest
13
+ end
14
+
15
+ [manifest_hash, cloud_manifest]
16
+ end
17
+
18
+ private
19
+
20
+ CLOUD_MANIFEST_KEYS = ['resource_pools','compilation','disk_pools','networks']
21
+ def cloud_manifest_from_deployment_manifest(deployment_manifest)
22
+ cloud_manifest = {}
23
+ CLOUD_MANIFEST_KEYS.each do |key|
24
+ cloud_manifest[key] = deployment_manifest[key] if deployment_manifest.has_key? key
25
+ end
26
+ cloud_manifest
27
+ end
28
+
29
+ def migrate_releases(manifest_hash)
30
+ if manifest_hash.has_key?('release')
31
+ raise(
32
+ Bosh::Director::DeploymentAmbiguousReleaseSpec,
33
+ "Deployment manifest contains both 'release' and 'releases' sections, please use one of the two."
34
+ ) if manifest_hash.has_key?('releases')
35
+
36
+ legacy_release = manifest_hash.delete('release')
37
+ manifest_hash['releases'] = [legacy_release].compact
38
+ end
39
+ end
40
+
41
+ def verify_deployment_without_cloud_config(manifest_hash)
42
+ deployment_cloud_properties = manifest_hash.keys & CLOUD_MANIFEST_KEYS
43
+ if deployment_cloud_properties.any?
44
+ raise(
45
+ Bosh::Director::DeploymentInvalidProperty,
46
+ "Deployment manifest should not contain cloud config properties: #{deployment_cloud_properties}"
47
+ )
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -134,4 +134,4 @@ module Bosh::Director
134
134
  end
135
135
  end
136
136
  end
137
- end
137
+ end
@@ -43,7 +43,7 @@ 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
+ gateway_property = safe_property(subnet_spec, "gateway", class: String)
47
47
  if gateway_property
48
48
  @gateway = NetAddr::CIDR.create(gateway_property)
49
49
  unless @gateway.size == 1
@@ -62,8 +62,7 @@ module Bosh::Director
62
62
 
63
63
  @dns = dns_servers(@network.name, subnet_spec)
64
64
 
65
- @cloud_properties = safe_property(subnet_spec, "cloud_properties",
66
- :class => Hash)
65
+ @cloud_properties = safe_property(subnet_spec, "cloud_properties", class: Hash, default: {})
67
66
 
68
67
  @available_dynamic_ips = Set.new
69
68
  @available_static_ips = Set.new
@@ -163,4 +162,4 @@ module Bosh::Director
163
162
 
164
163
  end
165
164
  end
166
- end
165
+ end
@@ -8,8 +8,8 @@ module Bosh::Director
8
8
  WARNING = 4
9
9
  end
10
10
 
11
- def initialize(planner, nats_rpc, logger)
12
- @planner = planner
11
+ def initialize(name, nats_rpc, logger)
12
+ @name = name
13
13
  @logger = logger
14
14
  @nats_rpc = nats_rpc
15
15
  end
@@ -19,7 +19,7 @@ module Bosh::Director
19
19
  'id' => SecureRandom.uuid,
20
20
  'severity' => Severity::WARNING,
21
21
  'title' => 'director - begin update deployment',
22
- 'summary' => "Begin update deployment for #{@planner.canonical_name} against Director #{Bosh::Director::Config.uuid}",
22
+ 'summary' => "Begin update deployment for '#{@name}' against Director '#{Bosh::Director::Config.uuid}'",
23
23
  'created_at' => Time.now.to_i
24
24
  }
25
25
 
@@ -32,7 +32,7 @@ module Bosh::Director
32
32
  'id' => SecureRandom.uuid,
33
33
  'severity' => Severity::WARNING,
34
34
  'title' => 'director - finish update deployment',
35
- 'summary' => "Finish update deployment for #{@planner.canonical_name} against Director #{Bosh::Director::Config.uuid}",
35
+ 'summary' => "Finish update deployment for '#{@name}' against Director '#{Bosh::Director::Config.uuid}'",
36
36
  'created_at' => Time.now.to_i
37
37
  }
38
38
 
@@ -45,7 +45,7 @@ module Bosh::Director
45
45
  'id' => SecureRandom.uuid,
46
46
  'severity' => Severity::ERROR,
47
47
  'title' => 'director - error during update deployment',
48
- 'summary' => "Error during update deployment for #{@planner.canonical_name} against Director #{Bosh::Director::Config.uuid}: #{exception.inspect}",
48
+ 'summary' => "Error during update deployment for '#{@name}' against Director '#{Bosh::Director::Config.uuid}': #{exception.inspect}",
49
49
  'created_at' => Time.now.to_i
50
50
  }
51
51
 
@@ -1,5 +1,7 @@
1
1
  require 'bosh/director/deployment_plan/deployment_spec_parser'
2
+ require 'bosh/director/deployment_plan/cloud_manifest_parser'
2
3
  require 'bosh/director/deployment_plan/disk_pool'
4
+ require 'forwardable'
3
5
 
4
6
  module Bosh::Director
5
7
  # Encapsulates essential director data structures retrieved
@@ -9,6 +11,7 @@ module Bosh::Director
9
11
  include LockHelper
10
12
  include DnsHelper
11
13
  include ValidationHelper
14
+ extend Forwardable
12
15
 
13
16
  # @return [String] Deployment name
14
17
  attr_reader :name
@@ -21,10 +24,6 @@ module Bosh::Director
21
24
 
22
25
  attr_accessor :properties
23
26
 
24
- # @return [Bosh::Director::DeploymentPlan::CompilationConfig]
25
- # Resource pool and other configuration for compilation workers
26
- attr_accessor :compilation
27
-
28
27
  # @return [Bosh::Director::DeploymentPlan::UpdateConfig]
29
28
  # Default job update configuration
30
29
  attr_accessor :update
@@ -46,33 +45,15 @@ module Bosh::Director
46
45
  # @return [Boolean] Indicates whether VMs should be recreated
47
46
  attr_reader :recreate
48
47
 
49
- # @param [Hash] manifest Raw deployment manifest
50
- # @param [Hash] options Additional options for deployment
51
- # (e.g. job_states, job_rename)
52
- # @param [Bosh::Director::EventLog::Log]
53
- # event_log Event log for recording deprecations
54
- # @param [Logger]
55
- # logger Log for director logging
56
- # @return [Bosh::Director::DeploymentPlan::Planner]
57
- def self.parse(manifest, cloud_config, options, event_log, logger)
58
- parser = DeploymentSpecParser.new(event_log, logger)
59
- parser.parse(manifest, cloud_config, options)
60
- end
48
+ def initialize(attrs, manifest_text, cloud_config, deployment_model, options = {})
49
+ @name = attrs.fetch(:name)
50
+ @properties = attrs.fetch(:properties)
51
+ @releases = {}
61
52
 
62
- def initialize(name, manifest_text, cloud_config, options = {})
63
- raise ArgumentError, 'name must not be nil' unless name
64
- @name = name
65
53
  @manifest_text = manifest_text
66
54
  @cloud_config = cloud_config
67
-
68
- @model = nil
69
- @properties = {}
70
- @releases = {}
71
- @networks = {}
72
- @networks_canonical_name_index = Set.new
73
-
74
- @resource_pools = {}
75
- @disk_pools = {}
55
+ @cloud_planner = CloudPlanner.new(cloud_config)
56
+ @model = deployment_model
76
57
 
77
58
  @jobs = []
78
59
  @jobs_name_index = {}
@@ -88,110 +69,21 @@ module Bosh::Director
88
69
  @recreate = !!options['recreate']
89
70
  end
90
71
 
72
+ def_delegators :@cloud_planner, :add_network, :networks, :network,
73
+ :add_resource_pool, :resource_pools, :resource_pool,
74
+ :add_disk_pool, :disk_pools, :disk_pool,
75
+ :compilation, :compilation=
76
+
91
77
  def canonical_name
92
78
  canonical(@name)
93
79
  end
94
80
 
95
- # Looks up deployment model in DB or creates one if needed
96
- # @return [void]
97
- def bind_model
98
- attrs = {:name => @name}
99
-
100
- Models::Deployment.db.transaction do
101
- deployment = Models::Deployment.find(attrs)
102
-
103
- # Canonical uniqueness is not enforced in the DB
104
- if deployment.nil?
105
- Models::Deployment.each do |other|
106
- if canonical(other.name) == canonical_name
107
- raise DeploymentCanonicalNameTaken,
108
- "Invalid deployment name `#{@name}', " +
109
- 'canonical name already taken'
110
- end
111
- end
112
- deployment = Models::Deployment.create(attrs)
113
- end
114
-
115
- @model = deployment
116
- end
117
- end
118
-
119
81
  # Returns a list of VMs in the deployment (according to DB)
120
82
  # @return [Array<Models::Vm>]
121
83
  def vms
122
- if @model.nil?
123
- raise DirectorError, "Can't get VMs list, deployment model is unbound"
124
- end
125
84
  @model.vms
126
85
  end
127
86
 
128
- # Adds a network by name
129
- # @param [Bosh::Director::DeploymentPlan::Network] network
130
- def add_network(network)
131
- if @networks_canonical_name_index.include?(network.canonical_name)
132
- raise DeploymentCanonicalNetworkNameTaken,
133
- "Invalid network name `#{network.name}', " +
134
- 'canonical name already taken'
135
- end
136
-
137
- @networks[network.name] = network
138
- @networks_canonical_name_index << network.canonical_name
139
- end
140
-
141
- # Returns all networks in a deployment plan
142
- # @return [Array<Bosh::Director::DeploymentPlan::Network>]
143
- def networks
144
- @networks.values
145
- end
146
-
147
- # Returns a named network
148
- # @param [String] name
149
- # @return [Bosh::Director::DeploymentPlan::Network]
150
- def network(name)
151
- @networks[name]
152
- end
153
-
154
- # Adds a resource pool by name
155
- # @param [Bosh::Director::DeploymentPlan::ResourcePool] resource_pool
156
- def add_resource_pool(resource_pool)
157
- if @resource_pools[resource_pool.name]
158
- raise DeploymentDuplicateResourcePoolName,
159
- "Duplicate resource pool name `#{resource_pool.name}'"
160
- end
161
- @resource_pools[resource_pool.name] = resource_pool
162
- end
163
-
164
- # Returns all resource pools in a deployment plan
165
- # @return [Array<Bosh::Director::DeploymentPlan::ResourcePool>]
166
- def resource_pools
167
- @resource_pools.values
168
- end
169
-
170
- # Returns a named resource pool spec
171
- # @param [String] name Resource pool name
172
- # @return [Bosh::Director::DeploymentPlan::ResourcePool]
173
- def resource_pool(name)
174
- @resource_pools[name]
175
- end
176
-
177
- # Adds a disk pool by name
178
- # @param [Bosh::Director::DeploymentPlan::DiskPool] disk_pool
179
- def add_disk_pool(disk_pool)
180
- if @disk_pools[disk_pool.name]
181
- raise DeploymentDuplicateDiskPoolName,
182
- "Duplicate disk pool name `#{disk_pool.name}'"
183
- end
184
- @disk_pools[disk_pool.name] = disk_pool
185
- end
186
-
187
- def disk_pools
188
- @disk_pools.values
189
- end
190
-
191
- def disk_pool(name)
192
- @disk_pools[name]
193
- end
194
-
195
87
  # Adds a release by name
196
88
  # @param [Bosh::Director::DeploymentPlan::ReleaseVersion] release
197
89
  def add_release(release)
@@ -287,5 +179,87 @@ module Bosh::Director
287
179
  end
288
180
  end
289
181
  end
182
+
183
+ class CloudPlanner
184
+ # @return [Bosh::Director::DeploymentPlan::CompilationConfig]
185
+ # Resource pool and other configuration for compilation workers
186
+ attr_accessor :compilation
187
+
188
+ def initialize(cloud_config)
189
+ @cloud_config = cloud_config
190
+ @networks_canonical_name_index = Set.new
191
+
192
+ @networks = {}
193
+ @resource_pools = {}
194
+ @disk_pools = {}
195
+ end
196
+
197
+ # Adds a resource pool by name
198
+ # @param [Bosh::Director::DeploymentPlan::ResourcePool] resource_pool
199
+ def add_resource_pool(resource_pool)
200
+ if @resource_pools[resource_pool.name]
201
+ raise DeploymentDuplicateResourcePoolName,
202
+ "Duplicate resource pool name `#{resource_pool.name}'"
203
+ end
204
+ @resource_pools[resource_pool.name] = resource_pool
205
+ end
206
+
207
+ # Returns all resource pools in a deployment plan
208
+ # @return [Array<Bosh::Director::DeploymentPlan::ResourcePool>]
209
+ def resource_pools
210
+ @resource_pools.values
211
+ end
212
+
213
+ # Returns a named resource pool spec
214
+ # @param [String] name Resource pool name
215
+ # @return [Bosh::Director::DeploymentPlan::ResourcePool]
216
+ def resource_pool(name)
217
+ @resource_pools[name]
218
+ end
219
+
220
+ # Adds a network by name
221
+ # @param [Bosh::Director::DeploymentPlan::Network] network
222
+ def add_network(network)
223
+ if @networks_canonical_name_index.include?(network.canonical_name)
224
+ raise DeploymentCanonicalNetworkNameTaken,
225
+ "Invalid network name `#{network.name}', " +
226
+ 'canonical name already taken'
227
+ end
228
+
229
+ @networks[network.name] = network
230
+ @networks_canonical_name_index << network.canonical_name
231
+ end
232
+
233
+ # Returns all networks in a deployment plan
234
+ # @return [Array<Bosh::Director::DeploymentPlan::Network>]
235
+ def networks
236
+ @networks.values
237
+ end
238
+
239
+ # Returns a named network
240
+ # @param [String] name
241
+ # @return [Bosh::Director::DeploymentPlan::Network]
242
+ def network(name)
243
+ @networks[name]
244
+ end
245
+
246
+ # Adds a disk pool by name
247
+ # @param [Bosh::Director::DeploymentPlan::DiskPool] disk_pool
248
+ def add_disk_pool(disk_pool)
249
+ if @disk_pools[disk_pool.name]
250
+ raise DeploymentDuplicateDiskPoolName,
251
+ "Duplicate disk pool name `#{disk_pool.name}'"
252
+ end
253
+ @disk_pools[disk_pool.name] = disk_pool
254
+ end
255
+
256
+ def disk_pools
257
+ @disk_pools.values
258
+ end
259
+
260
+ def disk_pool(name)
261
+ @disk_pools[name]
262
+ end
263
+ end
290
264
  end
291
265
  end
@@ -0,0 +1,148 @@
1
+ module Bosh
2
+ module Director
3
+ module DeploymentPlan
4
+ class PlannerFactory
5
+ def self.create(event_log, logger)
6
+ deployment_manifest_migrator = Bosh::Director::DeploymentPlan::ManifestMigrator.new
7
+ canonicalizer = Class.new { include Bosh::Director::DnsHelper }.new
8
+ deployment_repo = Bosh::Director::DeploymentPlan::DeploymentRepo.new(canonicalizer)
9
+
10
+ new(
11
+ canonicalizer,
12
+ deployment_manifest_migrator,
13
+ deployment_repo,
14
+ event_log,
15
+ logger
16
+ )
17
+ end
18
+
19
+ def initialize(canonicalizer, deployment_manifest_migrator, deployment_repo, event_log, logger)
20
+ @canonicalizer = canonicalizer
21
+ @deployment_manifest_migrator = deployment_manifest_migrator
22
+ @deployment_repo = deployment_repo
23
+ @event_log = event_log
24
+ @logger = logger
25
+ end
26
+
27
+ def planner(manifest_hash, cloud_config, plan_options)
28
+ planner = planner_without_vm_binding(manifest_hash, cloud_config, plan_options)
29
+ bind_vms(planner)
30
+ end
31
+
32
+ def planner_without_vm_binding(manifest_hash, cloud_config, options)
33
+ deployment_manifest, cloud_manifest = @deployment_manifest_migrator.migrate(manifest_hash, cloud_config)
34
+ name = deployment_manifest['name']
35
+
36
+ deployment_model = nil
37
+ @event_log.track('Binding deployment') do
38
+ @logger.info('Binding deployment')
39
+ deployment_model = @deployment_repo.find_or_create_by_name(name)
40
+ end
41
+
42
+ attrs = {
43
+ name: name,
44
+ properties: deployment_manifest.fetch('properties', {}),
45
+ }
46
+ assemble_without_vm_binding(attrs, deployment_manifest, cloud_manifest, deployment_model, cloud_config, options)
47
+ end
48
+
49
+ private
50
+
51
+ def deployment_name(manifest_hash)
52
+ name = manifest_hash['name']
53
+ @canonicalizer.canonical(name)
54
+ end
55
+
56
+ def assemble_without_vm_binding(attrs, deployment_manifest, cloud_manifest, deployment_model, cloud_config, options)
57
+ plan_options = {
58
+ 'recreate' => !!options['recreate'],
59
+ 'job_states' => options['job_states'] || {},
60
+ 'job_rename' => options['job_rename'] || {}
61
+ }
62
+ @logger.info('Creating deployment plan')
63
+ @logger.info("Deployment plan options: #{plan_options.pretty_inspect}")
64
+
65
+ deployment = Planner.new(attrs, deployment_manifest, cloud_config, deployment_model, plan_options)
66
+ deployment = CloudManifestParser.new(deployment, @logger).parse(cloud_manifest)
67
+ DeploymentSpecParser.new(deployment, @event_log, @logger).parse(deployment_manifest, plan_options)
68
+ end
69
+
70
+ def bind_vms(planner)
71
+ stemcell_manager = Api::StemcellManager.new
72
+ cloud = Config.cloud
73
+ blobstore = nil # not used for this assembler purposes
74
+ director_job = nil
75
+ assembler = DeploymentPlan::Assembler.new(
76
+ planner,
77
+ stemcell_manager,
78
+ cloud,
79
+ blobstore,
80
+ @logger,
81
+ @event_log
82
+ )
83
+ @logger.info('Created deployment plan')
84
+
85
+ run_prepare_step(assembler)
86
+
87
+ DeploymentPlan::Steps::PackageCompileStep.new(
88
+ planner,
89
+ cloud,
90
+ @logger,
91
+ @event_log,
92
+ director_job
93
+ ).perform
94
+ @event_log.begin_stage('Preparing DNS', 1)
95
+ track_and_log('Binding DNS') do
96
+ assembler.bind_dns
97
+ end
98
+
99
+ planner
100
+ end
101
+
102
+ def run_prepare_step(assembler)
103
+ @event_log.begin_stage('Preparing deployment', 9)
104
+ @logger.info('Preparing deployment')
105
+
106
+ track_and_log('Binding releases') do
107
+ assembler.bind_releases
108
+ end
109
+
110
+ track_and_log('Binding existing deployment') do
111
+ assembler.bind_existing_deployment
112
+ end
113
+
114
+ track_and_log('Binding resource pools') do
115
+ assembler.bind_resource_pools
116
+ end
117
+
118
+ track_and_log('Binding stemcells') do
119
+ assembler.bind_stemcells
120
+ end
121
+
122
+ track_and_log('Binding templates') do
123
+ assembler.bind_templates
124
+ end
125
+
126
+ track_and_log('Binding properties') do
127
+ assembler.bind_properties
128
+ end
129
+
130
+ track_and_log('Binding unallocated VMs') do
131
+ assembler.bind_unallocated_vms
132
+ end
133
+
134
+ track_and_log('Binding instance networks') do
135
+ assembler.bind_instance_networks
136
+ end
137
+ end
138
+
139
+ def track_and_log(message)
140
+ @event_log.track(message) do
141
+ @logger.info(message)
142
+ yield
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end