bosh-director 1.3232.24.0 → 1.3262.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/db/migrations/director/20160414183654_set_teams_on_task.rb +7 -0
  3. data/db/migrations/director/20160427164345_add_teams.rb +48 -0
  4. data/db/migrations/director/20160511191928_ephemeral_blobs.rb +10 -0
  5. data/db/migrations/director/20160513102035_add_tracking_to_instance.rb +7 -0
  6. data/db/migrations/director/20160531164756_add_local_dns_blobs.rb +14 -0
  7. data/lib/bosh/director.rb +5 -1
  8. data/lib/bosh/director/api.rb +1 -0
  9. data/lib/bosh/director/api/api_helper.rb +2 -2
  10. data/lib/bosh/director/api/controllers/cleanup_controller.rb +1 -1
  11. data/lib/bosh/director/api/controllers/deployments_controller.rb +39 -25
  12. data/lib/bosh/director/api/controllers/disks_controller.rb +2 -1
  13. data/lib/bosh/director/api/controllers/events_controller.rb +34 -0
  14. data/lib/bosh/director/api/controllers/releases_controller.rb +1 -1
  15. data/lib/bosh/director/api/controllers/resurrection_controller.rb +1 -1
  16. data/lib/bosh/director/api/controllers/stemcells_controller.rb +1 -1
  17. data/lib/bosh/director/api/controllers/tasks_controller.rb +31 -46
  18. data/lib/bosh/director/api/controllers/users_controller.rb +2 -2
  19. data/lib/bosh/director/api/controllers/vms_controller.rb +18 -0
  20. data/lib/bosh/director/api/deployment_manager.rb +3 -3
  21. data/lib/bosh/director/api/instance_ignore_manager.rb +11 -0
  22. data/lib/bosh/director/api/instance_manager.rb +3 -3
  23. data/lib/bosh/director/api/local_identity_provider.rb +1 -1
  24. data/lib/bosh/director/api/problem_manager.rb +3 -3
  25. data/lib/bosh/director/api/release_manager.rb +9 -4
  26. data/lib/bosh/director/api/resurrector_manager.rb +13 -1
  27. data/lib/bosh/director/api/route_configuration.rb +1 -0
  28. data/lib/bosh/director/api/snapshot_manager.rb +2 -2
  29. data/lib/bosh/director/api/stemcell_manager.rb +29 -9
  30. data/lib/bosh/director/api/task_helper.rb +4 -3
  31. data/lib/bosh/director/api/uaa_identity_provider.rb +9 -3
  32. data/lib/bosh/director/api/user/config_user_manager.rb +1 -1
  33. data/lib/bosh/director/api/user/database_user_manager.rb +2 -2
  34. data/lib/bosh/director/cidr_range_combiner.rb +51 -0
  35. data/lib/bosh/director/cloudcheck_helper.rb +17 -6
  36. data/lib/bosh/director/config.rb +27 -1
  37. data/lib/bosh/director/db_backup/adapter/postgres.rb +0 -1
  38. data/lib/bosh/director/deployment_plan.rb +1 -1
  39. data/lib/bosh/director/deployment_plan/assembler.rb +8 -5
  40. data/lib/bosh/director/deployment_plan/deployment_repo.rb +10 -3
  41. data/lib/bosh/director/deployment_plan/deployment_spec_parser.rb +17 -6
  42. data/lib/bosh/director/deployment_plan/global_network_resolver.rb +44 -23
  43. data/lib/bosh/director/deployment_plan/instance.rb +2 -2
  44. data/lib/bosh/director/deployment_plan/{job.rb → instance_group.rb} +5 -5
  45. data/lib/bosh/director/deployment_plan/{job_spec_parser.rb → instance_group_spec_parser.rb} +17 -15
  46. data/lib/bosh/director/deployment_plan/instance_plan.rb +14 -10
  47. data/lib/bosh/director/deployment_plan/instance_planner.rb +22 -0
  48. data/lib/bosh/director/deployment_plan/job_migrator.rb +2 -2
  49. data/lib/bosh/director/deployment_plan/links/link_lookup.rb +3 -3
  50. data/lib/bosh/director/deployment_plan/links/link_path.rb +2 -2
  51. data/lib/bosh/director/deployment_plan/links/links_resolver.rb +1 -1
  52. data/lib/bosh/director/deployment_plan/manual_network.rb +1 -1
  53. data/lib/bosh/director/deployment_plan/manual_network_subnet.rb +1 -1
  54. data/lib/bosh/director/deployment_plan/placement_planner/availability_zone_picker.rb +53 -1
  55. data/lib/bosh/director/deployment_plan/placement_planner/static_ips_availability_zone_picker.rb +39 -1
  56. data/lib/bosh/director/deployment_plan/placement_planner/unplaced_existing_instances.rb +4 -0
  57. data/lib/bosh/director/deployment_plan/planner.rb +37 -31
  58. data/lib/bosh/director/deployment_plan/planner_factory.rb +26 -11
  59. data/lib/bosh/director/deployment_plan/runtime_manifest_parser.rb +15 -6
  60. data/lib/bosh/director/deployment_plan/steps/update_step.rb +1 -1
  61. data/lib/bosh/director/deployment_plan/template.rb +14 -1
  62. data/lib/bosh/director/dns/blobstore_dns_publisher.rb +35 -0
  63. data/lib/bosh/director/dns/dns_manager.rb +37 -74
  64. data/lib/bosh/director/errand/job_manager.rb +1 -1
  65. data/lib/bosh/director/error_ignorer.rb +1 -2
  66. data/lib/bosh/director/errors.rb +4 -0
  67. data/lib/bosh/director/event_log.rb +10 -2
  68. data/lib/bosh/director/instance_deleter.rb +11 -2
  69. data/lib/bosh/director/instance_updater.rb +21 -25
  70. data/lib/bosh/director/instance_updater/instance_state.rb +24 -2
  71. data/lib/bosh/director/instance_updater/state_applier.rb +4 -4
  72. data/lib/bosh/director/job_queue.rb +2 -2
  73. data/lib/bosh/director/job_updater.rb +3 -1
  74. data/lib/bosh/director/jobs/attach_disk.rb +7 -2
  75. data/lib/bosh/director/jobs/cleanup_artifacts.rb +15 -5
  76. data/lib/bosh/director/jobs/cloud_check/apply_resolutions.rb +2 -0
  77. data/lib/bosh/director/jobs/cloud_check/scan_and_fix.rb +5 -5
  78. data/lib/bosh/director/jobs/db_job.rb +10 -13
  79. data/lib/bosh/director/jobs/delete_deployment.rb +13 -1
  80. data/lib/bosh/director/jobs/delete_vm.rb +58 -0
  81. data/lib/bosh/director/jobs/export_release.rb +11 -4
  82. data/lib/bosh/director/jobs/helpers.rb +2 -0
  83. data/lib/bosh/director/jobs/helpers/config_parser.rb +66 -0
  84. data/lib/bosh/director/jobs/helpers/deep_hash_replacement.rb +38 -0
  85. data/lib/bosh/director/jobs/run_errand.rb +1 -1
  86. data/lib/bosh/director/jobs/ssh.rb +3 -2
  87. data/lib/bosh/director/jobs/update_deployment.rb +73 -14
  88. data/lib/bosh/director/jobs/update_release.rb +3 -1
  89. data/lib/bosh/director/jobs/update_stemcell.rb +1 -0
  90. data/lib/bosh/director/jobs/vm_state.rb +4 -3
  91. data/lib/bosh/director/legacy_deployment_helper.rb +7 -0
  92. data/lib/bosh/director/manifest/diff_lines.rb +4 -0
  93. data/lib/bosh/director/manifest/manifest.rb +18 -6
  94. data/lib/bosh/director/models.rb +3 -0
  95. data/lib/bosh/director/models/deployment.rb +17 -8
  96. data/lib/bosh/director/models/deployment_problem.rb +2 -2
  97. data/lib/bosh/director/models/ephemeral_blob.rb +11 -0
  98. data/lib/bosh/director/models/event.rb +2 -2
  99. data/lib/bosh/director/models/instance.rb +35 -5
  100. data/lib/bosh/director/models/local_dns_blob.rb +4 -0
  101. data/lib/bosh/director/models/orphan_disk.rb +2 -2
  102. data/lib/bosh/director/models/package.rb +2 -2
  103. data/lib/bosh/director/models/persistent_disk.rb +2 -2
  104. data/lib/bosh/director/models/task.rb +15 -0
  105. data/lib/bosh/director/models/team.rb +35 -0
  106. data/lib/bosh/director/models/template.rb +6 -2
  107. data/lib/bosh/director/nats_rpc.rb +3 -3
  108. data/lib/bosh/director/permission_authorizer.rb +14 -4
  109. data/lib/bosh/director/post_deployment_script_runner.rb +5 -4
  110. data/lib/bosh/director/problem_handlers/missing_vm.rb +7 -2
  111. data/lib/bosh/director/problem_handlers/unresponsive_agent.rb +11 -1
  112. data/lib/bosh/director/problem_resolver.rb +1 -1
  113. data/lib/bosh/director/problem_scanner/disk_scan_stage.rb +1 -1
  114. data/lib/bosh/director/problem_scanner/vm_scan_stage.rb +5 -1
  115. data/lib/bosh/director/version.rb +1 -1
  116. data/lib/bosh/director/vm_deleter.rb +8 -7
  117. data/lib/bosh/director/worker.rb +1 -0
  118. metadata +36 -34
@@ -207,11 +207,11 @@ module Bosh::Director
207
207
  end
208
208
 
209
209
  def current_job_spec
210
- @model.spec['job']
210
+ @model.spec_p('job')
211
211
  end
212
212
 
213
213
  def current_packages
214
- @model.spec['packages']
214
+ @model.spec_p('packages')
215
215
  end
216
216
 
217
217
  def current_job_state
@@ -1,9 +1,9 @@
1
- require 'bosh/director/deployment_plan/job_spec_parser'
1
+ require 'bosh/director/deployment_plan/instance_group_spec_parser'
2
2
  require 'bosh/template/property_helper'
3
3
 
4
4
  module Bosh::Director
5
5
  module DeploymentPlan
6
- class Job
6
+ class InstanceGroup
7
7
  include Bosh::Template::PropertyHelper
8
8
 
9
9
  VALID_LIFECYCLE_PROFILES = %w(service errand)
@@ -85,9 +85,9 @@ module Bosh::Director
85
85
 
86
86
  attr_accessor :did_change
87
87
 
88
- def self.parse(plan, job_spec, event_log, logger)
89
- parser = JobSpecParser.new(plan, event_log, logger)
90
- parser.parse(job_spec)
88
+ def self.parse(plan, job_spec, event_log, logger, parse_options = {})
89
+ parser = InstanceGroupSpecParser.new(plan, event_log, logger)
90
+ parser.parse(job_spec, parse_options)
91
91
  end
92
92
 
93
93
  def initialize(logger)
@@ -2,7 +2,7 @@ require 'bosh/template/property_helper'
2
2
 
3
3
  module Bosh::Director
4
4
  module DeploymentPlan
5
- class JobSpecParser
5
+ class InstanceGroupSpecParser
6
6
  include ValidationHelper
7
7
  include Bosh::Template::PropertyHelper
8
8
  include IpUtil
@@ -16,9 +16,9 @@ module Bosh::Director
16
16
 
17
17
  # @param [Hash] job_spec Raw job spec from the deployment manifest
18
18
  # @return [DeploymentPlan::Job] Job as build from job_spec
19
- def parse(job_spec)
19
+ def parse(job_spec, options = {})
20
20
  @job_spec = job_spec
21
- @job = Job.new(@logger)
21
+ @job = InstanceGroup.new(@logger)
22
22
 
23
23
  parse_name
24
24
  parse_lifecycle
@@ -35,7 +35,10 @@ module Bosh::Director
35
35
  parse_resource_pool
36
36
  check_remove_dev_tools
37
37
 
38
- parse_update_config
38
+ parse_options = {}
39
+ parse_options['canaries'] = options['canaries'] if options['canaries']
40
+ parse_options['max_in_flight'] = options['max_in_flight'] if options['max_in_flight']
41
+ parse_update_config(parse_options)
39
42
 
40
43
  networks = JobNetworksParser.new(Network::VALID_DEFAULTS).parse(@job_spec, @job.name, @deployment.networks)
41
44
  @job.networks = networks
@@ -63,13 +66,13 @@ module Bosh::Director
63
66
  lifecycle = safe_property(@job_spec, "lifecycle",
64
67
  :class => String,
65
68
  :optional => true,
66
- :default => Job::DEFAULT_LIFECYCLE_PROFILE,
69
+ :default => InstanceGroup::DEFAULT_LIFECYCLE_PROFILE,
67
70
  )
68
71
 
69
- unless Job::VALID_LIFECYCLE_PROFILES.include?(lifecycle)
72
+ unless InstanceGroup::VALID_LIFECYCLE_PROFILES.include?(lifecycle)
70
73
  raise JobInvalidLifecycle,
71
74
  "Invalid lifecycle '#{lifecycle}' for '#{@job.name}', " +
72
- "valid lifecycle profiles are: #{Job::VALID_LIFECYCLE_PROFILES.join(', ')}"
75
+ "valid lifecycle profiles are: #{InstanceGroup::VALID_LIFECYCLE_PROFILES.join(', ')}"
73
76
  end
74
77
 
75
78
  @job.lifecycle = lifecycle
@@ -201,8 +204,7 @@ module Bosh::Director
201
204
  @job.templates.each do |template|
202
205
  if all_names.count(template.name) > 1
203
206
  raise JobInvalidTemplates,
204
- "Colocated job template '#{template.name}' has the same name in multiple releases. " +
205
- "BOSH cannot currently colocate two job templates with identical names from separate releases."
207
+ "Colocated job '#{template.name}' is already added to the instance group '#{@job.name}'"
206
208
  end
207
209
  end
208
210
  end
@@ -325,9 +327,9 @@ module Bosh::Director
325
327
  @job.env = Env.new(env_hash)
326
328
  end
327
329
 
328
- def parse_update_config
330
+ def parse_update_config(parse_options)
329
331
  update_spec = safe_property(@job_spec, "update", class: Hash, optional: true)
330
- @job.update = UpdateConfig.new(update_spec, @deployment.update)
332
+ @job.update = UpdateConfig.new((update_spec || {}).merge(parse_options), @deployment.update)
331
333
  end
332
334
 
333
335
  def parse_desired_instances(availability_zones, networks)
@@ -344,17 +346,17 @@ module Bosh::Director
344
346
  end
345
347
 
346
348
  instance_states.each_pair do |index_or_id, state|
347
- unless Job::VALID_JOB_STATES.include?(state)
349
+ unless InstanceGroup::VALID_JOB_STATES.include?(state)
348
350
  raise JobInvalidInstanceState,
349
- "Invalid state '#{state}' for '#{@job.name}/#{index_or_id}', valid states are: #{Job::VALID_JOB_STATES.join(", ")}"
351
+ "Invalid state '#{state}' for '#{@job.name}/#{index_or_id}', valid states are: #{InstanceGroup::VALID_JOB_STATES.join(", ")}"
350
352
  end
351
353
 
352
354
  @job.instance_states[index_or_id] = state
353
355
  end
354
356
 
355
- if @job.state && !Job::VALID_JOB_STATES.include?(@job.state)
357
+ if @job.state && !InstanceGroup::VALID_JOB_STATES.include?(@job.state)
356
358
  raise JobInvalidJobState,
357
- "Invalid state '#{@job.state}' for '#{@job.name}', valid states are: #{Job::VALID_JOB_STATES.join(", ")}"
359
+ "Invalid state '#{@job.state}' for '#{@job.name}', valid states are: #{InstanceGroup::VALID_JOB_STATES.join(", ")}"
358
360
  end
359
361
 
360
362
  job_size.times.map { DesiredInstance.new(@job, @deployment) }
@@ -68,6 +68,10 @@ module Bosh
68
68
  new? ? instance.model : existing_instance
69
69
  end
70
70
 
71
+ def should_be_ignored?
72
+ !instance_model.nil? && instance_model.ignore
73
+ end
74
+
71
75
  def needs_restart?
72
76
  @instance.virtual_state == 'restart'
73
77
  end
@@ -85,7 +89,7 @@ module Bosh
85
89
  desired_network_plans = network_plans.select(&:desired?)
86
90
  obsolete_network_plans = network_plans.select(&:obsolete?)
87
91
 
88
- old_network_settings = new? ? {} : @existing_instance.spec['networks']
92
+ old_network_settings = new? ? {} : @existing_instance.spec_p('networks')
89
93
  new_network_settings = network_settings.to_hash
90
94
 
91
95
  changed = false
@@ -134,8 +138,8 @@ module Bosh
134
138
  end
135
139
 
136
140
  def configuration_changed?
137
- changed = instance.configuration_hash != instance_model.spec['configuration_hash']
138
- log_changes(__method__, instance_model.spec['configuration_hash'], instance.configuration_hash, instance) if changed
141
+ changed = instance.configuration_hash != instance_model.spec_p('configuration_hash')
142
+ log_changes(__method__, instance_model.spec_p('configuration_hash'), instance.configuration_hash, instance) if changed
139
143
  changed
140
144
  end
141
145
 
@@ -231,7 +235,7 @@ module Bosh
231
235
  # The agent job spec could be in legacy form. job_spec cannot be,
232
236
  # though, because we got it from the spec function in job.rb which
233
237
  # automatically makes it non-legacy.
234
- converted_current = Job.convert_from_legacy_spec(@instance.current_job_spec)
238
+ converted_current = InstanceGroup.convert_from_legacy_spec(@instance.current_job_spec)
235
239
  changed = job.spec != converted_current
236
240
  log_changes(__method__, converted_current, job.spec, @instance) if changed
237
241
  changed
@@ -245,7 +249,7 @@ module Bosh
245
249
  changed
246
250
  end
247
251
 
248
- def currently_detached?
252
+ def already_detached?
249
253
  return false if new?
250
254
 
251
255
  @existing_instance.state == 'detached'
@@ -279,13 +283,13 @@ module Bosh
279
283
  end
280
284
 
281
285
  def stemcell_changed?
282
- if @existing_instance && @instance.stemcell.name != @existing_instance.spec['stemcell']['name']
283
- log_changes(__method__, @existing_instance.spec['stemcell']['name'], @instance.stemcell.name, @existing_instance)
286
+ if @existing_instance && @instance.stemcell.name != @existing_instance.spec_p('stemcell.name')
287
+ log_changes(__method__, @existing_instance.spec_p('stemcell.name'), @instance.stemcell.name, @existing_instance)
284
288
  return true
285
289
  end
286
290
 
287
- if @existing_instance && @instance.stemcell.version != @existing_instance.spec['stemcell']['version']
288
- log_changes(__method__, "version: #{@existing_instance.spec['stemcell']['version']}", "version: #{@instance.stemcell.version}", @existing_instance)
291
+ if @existing_instance && @instance.stemcell.version != @existing_instance.spec_p('stemcell.version')
292
+ log_changes(__method__, "version: #{@existing_instance.spec_p('stemcell.version')}", "version: #{@instance.stemcell.version}", @existing_instance)
289
293
  return true
290
294
  end
291
295
 
@@ -323,7 +327,7 @@ module Bosh
323
327
 
324
328
  class ResurrectionInstancePlan < InstancePlan
325
329
  def network_settings_hash
326
- @existing_instance.spec['networks']
330
+ @existing_instance.spec_p('networks')
327
331
  end
328
332
 
329
333
  def spec
@@ -8,6 +8,10 @@ module Bosh
8
8
  end
9
9
 
10
10
  def plan_job_instances(job, desired_instances, existing_instance_models)
11
+ if existing_instance_models.count(&:ignore) > 0
12
+ fail_if_specifically_changing_state_of_ignored_vms(job, existing_instance_models)
13
+ end
14
+
11
15
  network_planner = NetworkPlanner::Planner.new(@logger)
12
16
  placement_plan = PlacementPlanner::Plan.new(@instance_plan_factory, network_planner, @logger)
13
17
  vip_networks, non_vip_networks = job.networks.to_a.partition(&:vip?)
@@ -32,6 +36,14 @@ module Bosh
32
36
  desired_job_names.include?(existing_instance_model.job) ||
33
37
  migrating_job_names.include?(existing_instance_model.job)
34
38
  end
39
+
40
+ obsolete_existing_instances.each do |instance_model|
41
+ if instance_model.ignore
42
+ raise DeploymentIgnoredInstancesDeletion, "You are trying to delete instance group '#{instance_model.job}', which " +
43
+ 'contains ignored instance(s). Operation not allowed.'
44
+ end
45
+ end
46
+
35
47
  obsolete_existing_instances.map do |obsolete_existing_instance|
36
48
  @instance_plan_factory.obsolete_instance_plan(obsolete_existing_instance)
37
49
  end
@@ -80,6 +92,16 @@ module Bosh
80
92
  end
81
93
  end
82
94
 
95
+ def fail_if_specifically_changing_state_of_ignored_vms(job, existing_instance_models)
96
+ ignored_models = existing_instance_models.select(&:ignore)
97
+ ignored_models.each do |model|
98
+ unless job.instance_states["#{model.index}"].nil?
99
+ raise JobInstanceIgnored, "You are trying to change the state of the ignored instance '#{model.job}/#{model.uuid}'. " +
100
+ 'This operation is not allowed. You need to unignore it first.'
101
+ end
102
+ end
103
+ end
104
+
83
105
  def log_outcome(instance_plans)
84
106
  instance_plans.select(&:new?).each do |instance_plan|
85
107
  instance = instance_plan.desired_instance
@@ -33,7 +33,7 @@ module Bosh::Director
33
33
  migrated_from_instances = []
34
34
 
35
35
  migrated_from_jobs.each do |migrated_from_job|
36
- existing_job = @deployment_plan.job(migrated_from_job.name)
36
+ existing_job = @deployment_plan.instance_group(migrated_from_job.name)
37
37
  if existing_job && existing_job.name != desired_job.name
38
38
  raise DeploymentInvalidMigratedFromJob,
39
39
  "Failed to migrate instance group '#{migrated_from_job.name}' to '#{desired_job_name}'. " +
@@ -41,7 +41,7 @@ module Bosh::Director
41
41
  "Please remove instance group '#{migrated_from_job.name}'."
42
42
  end
43
43
 
44
- other_jobs = @deployment_plan.jobs.reject { |job| job.name == desired_job_name }
44
+ other_jobs = @deployment_plan.instance_groups.reject { |job| job.name == desired_job_name }
45
45
 
46
46
  migrate_to_multiple_jobs = other_jobs.any? do |job|
47
47
  job.migrated_from.any? do |other_migrated_from_job|
@@ -3,7 +3,7 @@ module Bosh::Director
3
3
  # tested in link_resolver_spec
4
4
 
5
5
  class LinkLookupFactory
6
- def self.create(consumed_link, link_path, deployment_plan, link_network, consumes_job, consumes_template)
6
+ def self.create(consumed_link, link_path, deployment_plan, link_network)
7
7
  if link_path.deployment == deployment_plan.name
8
8
  PlannerLinkLookup.new(consumed_link, link_path, deployment_plan, link_network)
9
9
  else
@@ -24,7 +24,7 @@ module Bosh::Director
24
24
  def initialize(consumed_link, link_path, deployment_plan, link_network)
25
25
  @consumed_link = consumed_link
26
26
  @link_path = link_path
27
- @jobs = deployment_plan.jobs
27
+ @jobs = deployment_plan.instance_groups
28
28
  @link_network = link_network
29
29
  end
30
30
 
@@ -71,4 +71,4 @@ module Bosh::Director
71
71
  end
72
72
  end
73
73
  end
74
- end
74
+ end
@@ -55,7 +55,7 @@ module Bosh::Director
55
55
  link_network = link_info["network"]
56
56
  found_link_paths = []
57
57
 
58
- @deployment_plan.jobs.each do |provides_job|
58
+ @deployment_plan.instance_groups.each do |provides_job|
59
59
  if !link_network || provides_job.has_network?(link_network)
60
60
  provides_job.templates.each do |provides_template|
61
61
  if provides_template.link_infos.has_key?(provides_job.name) && provides_template.link_infos[provides_job.name].has_key?('provides')
@@ -106,7 +106,7 @@ module Bosh::Director
106
106
 
107
107
  def get_link_path_from_deployment_plan(name, link_network)
108
108
  found_link_paths = []
109
- @deployment_plan.jobs.each do |job|
109
+ @deployment_plan.instance_groups.each do |job|
110
110
  if !link_network || job.has_network?(link_network)
111
111
  job.templates.each do |template|
112
112
  if template.link_infos.has_key?(job.name) && template.link_infos[job.name].has_key?('provides')
@@ -33,7 +33,7 @@ module Bosh::Director
33
33
  job.add_resolved_link(link_name, link_path.manual_spec)
34
34
  else
35
35
  link_network = template.consumes_link_info(job.name, link_name)['network']
36
- link_lookup = LinkLookupFactory.create(consumed_link, link_path, @deployment_plan, link_network, job.name, template.name)
36
+ link_lookup = LinkLookupFactory.create(consumed_link, link_path, @deployment_plan, link_network)
37
37
  link_spec = link_lookup.find_link_spec
38
38
 
39
39
  unless link_spec
@@ -11,7 +11,7 @@ module Bosh::Director
11
11
  def self.parse(network_spec, availability_zones, global_network_resolver, logger)
12
12
  name = safe_property(network_spec, "name", :class => String)
13
13
 
14
- reserved_ranges = global_network_resolver.reserved_legacy_ranges(name)
14
+ reserved_ranges = global_network_resolver.reserved_ranges
15
15
  subnet_specs = safe_property(network_spec, 'subnets', :class => Array)
16
16
  subnets = []
17
17
  subnet_specs.each do |subnet_spec|
@@ -10,7 +10,7 @@ module Bosh::Director
10
10
  def self.parse(network_name, subnet_spec, availability_zones, legacy_reserved_ranges)
11
11
  @logger = Config.logger
12
12
 
13
- @logger.debug("reserved ranges #{legacy_reserved_ranges.inspect}")
13
+ @logger.debug("reserved ranges #{legacy_reserved_ranges.map {|r| r.first == r.last ? "#{r.first}" : "#{r.first}-#{r.last}"}.join(', ')}")
14
14
  range_property = safe_property(subnet_spec, "range", :class => String)
15
15
  range = NetAddr::CIDR.create(range_property)
16
16
 
@@ -12,12 +12,17 @@ module Bosh
12
12
  end
13
13
 
14
14
  def place_and_match_in(desired_instances, existing_instance_models)
15
+ validate_networks_not_changed_for_ignore_vms(existing_instance_models)
16
+
15
17
  unplaced_existing_instances = UnplacedExistingInstances.new(existing_instance_models)
16
18
  desired_azs_sorted = unplaced_existing_instances.azs_sorted_by_existing_instance_count_descending(@desired_azs)
17
19
  @logger.debug("Desired azs: #{desired_azs_sorted.inspect}")
20
+ validate_desired_azs_contains_all_azs_from_ignored_instances(unplaced_existing_instances, desired_instances)
21
+
18
22
  placed_instances = PlacedDesiredInstances.new(desired_azs_sorted)
19
23
 
20
- remaining_desired_instances = place_instances_that_have_persistent_disk_in_existing_az(desired_azs_sorted, desired_instances, placed_instances, unplaced_existing_instances)
24
+ remaining_desired_instances_minus_ignored = place_instances_that_have_ignore_flag_as_true(desired_azs_sorted, desired_instances, placed_instances, unplaced_existing_instances)
25
+ remaining_desired_instances = place_instances_that_have_persistent_disk_in_existing_az(desired_azs_sorted, remaining_desired_instances_minus_ignored, placed_instances, unplaced_existing_instances)
21
26
  balance_across_desired_azs(remaining_desired_instances, placed_instances, unplaced_existing_instances)
22
27
 
23
28
  obsolete_instance_plans(unplaced_existing_instances.unclaimed) +
@@ -27,6 +32,39 @@ module Bosh
27
32
 
28
33
  private
29
34
 
35
+ def place_instances_that_have_ignore_flag_as_true(desired_azs, desired_instances, placed_instances, unplaced_existing_instances)
36
+ return desired_instances if unplaced_existing_instances.ignored_instances.empty?
37
+
38
+ desired_instances = desired_instances.dup
39
+ return desired_instances if desired_azs.nil?
40
+ unplaced_existing_instances.ignored_instances.each do |existing_instance|
41
+ az = desired_azs.find { |az| az.name == existing_instance.availability_zone }
42
+ next if az.nil?
43
+ desired_instance = desired_instances.pop
44
+ unplaced_existing_instances.claim_instance(existing_instance)
45
+ placed_instances.record_placement(az, desired_instance, existing_instance)
46
+ end
47
+ desired_instances
48
+ end
49
+
50
+ def validate_desired_azs_contains_all_azs_from_ignored_instances(unplaced_existing_instances, desired_instances)
51
+ return if unplaced_existing_instances.ignored_instances.empty?
52
+
53
+ if unplaced_existing_instances.ignored_instances.count > desired_instances.count
54
+ @logger.info("Desired instances count, #{desired_instances.count}, is less than existing ignored instances, #{unplaced_existing_instances.ignored_instances.count}")
55
+ raise DeploymentIgnoredInstancesModification, "Instance Group '#{unplaced_existing_instances.ignored_instances.first.job}' has #{unplaced_existing_instances.ignored_instances.count} ignored instance(s)." +
56
+ " #{desired_instances.count} instance(s) of that instance group were requested. Deleting ignored instances is not allowed."
57
+ end
58
+
59
+ ignore_instances_az_names = unplaced_existing_instances.ignored_instances.map(&:availability_zone).compact.uniq
60
+ desired_az_names = @desired_azs.nil? ? [] : @desired_azs.map(&:name)
61
+ ignore_instances_az_names_attempted_to_be_deleted = ignore_instances_az_names - desired_az_names
62
+ unless ignore_instances_az_names_attempted_to_be_deleted.empty?
63
+ raise DeploymentIgnoredInstancesModification, "Instance Group '#{unplaced_existing_instances.ignored_instances.first.job}' no longer contains AZs " +
64
+ "#{ignore_instances_az_names_attempted_to_be_deleted} where ignored instance(s) exist."
65
+ end
66
+ end
67
+
30
68
  def place_instances_that_have_persistent_disk_in_existing_az(desired_azs, desired_instances, placed_instances, unplaced_existing_instances)
31
69
  desired_instances = desired_instances.dup
32
70
  return desired_instances if desired_azs.nil?
@@ -83,6 +121,20 @@ module Bosh
83
121
  instance_plan.network_plans << @network_planner.network_plan_with_dynamic_reservation(instance_plan, network)
84
122
  end
85
123
  end
124
+
125
+ def validate_networks_not_changed_for_ignore_vms(existing_instance_models)
126
+ existing_instance_models.each do |existing_instance_model|
127
+ next if !existing_instance_model.ignore
128
+
129
+ desired_networks_names = @networks.map(&:name).uniq.sort
130
+ existing_networks_names = existing_instance_model.ip_addresses.map(&:network_name).uniq.sort
131
+
132
+ if desired_networks_names != existing_networks_names
133
+ raise DeploymentIgnoredInstancesModification, "In instance group '#{existing_instance_model.job}', which contains ignored vms,"+
134
+ ' an attempt was made to modify the networks. This operation is not allowed.'
135
+ end
136
+ end
137
+ end
86
138
  end
87
139
  end
88
140
  end
@@ -18,14 +18,48 @@ module Bosh
18
18
  def place_and_match_in(desired_instances, existing_instance_models)
19
19
  @networks_to_static_ips.validate_azs_are_declared_in_job_and_subnets(@desired_azs)
20
20
  @networks_to_static_ips.validate_ips_are_in_desired_azs(@desired_azs)
21
+ validate_ignored_instances_networks(existing_instance_models)
22
+
21
23
  desired_instances = desired_instances.dup
22
24
 
23
25
  instance_plans = place_existing_instance_plans(desired_instances, existing_instance_models)
24
- place_new_instance_plans(desired_instances, instance_plans)
26
+ instance_plans = place_new_instance_plans(desired_instances, instance_plans)
27
+
28
+ if ignored_instances_are_obsolete?(instance_plans)
29
+ raise DeploymentIgnoredInstancesModification, "In instance group '#{@job_name}', an attempt was made to remove a static ip"+
30
+ ' that is used by an ignored instance. This operation is not allowed.'
31
+ end
32
+
33
+ instance_plans
25
34
  end
26
35
 
27
36
  private
28
37
 
38
+ def validate_ignored_instances_networks(existing_instance_models)
39
+ existing_instance_models.each do |existing_instance_model|
40
+ next if !existing_instance_model.ignore
41
+
42
+ # Validate that no networks were added or deleted
43
+ desired_networks_names = @job_networks.map(&:name).uniq.sort
44
+ existing_networks_names = existing_instance_model.ip_addresses.map(&:network_name).uniq.sort
45
+
46
+ if desired_networks_names != existing_networks_names
47
+ raise DeploymentIgnoredInstancesModification, "In instance group '#{@job_name}', which contains ignored vms,"+
48
+ ' an attempt was made to modify the networks. This operation is not allowed.'
49
+ end
50
+
51
+ # Validate that no ip addresses, that were assigned to an ignored VM, have been removed
52
+ existing_instance_model.ip_addresses.each do |ip_address|
53
+ ignored_vm_network = @job_networks.select { |n| n.name == ip_address.network_name }.first
54
+
55
+ if !ignored_vm_network.static_ips.include?(ip_address.address)
56
+ raise DeploymentIgnoredInstancesModification, "In instance group '#{@job_name}', an attempt was made to remove a static ip"+
57
+ ' that is used by an ignored instance. This operation is not allowed.'
58
+ end
59
+ end
60
+ end
61
+ end
62
+
29
63
  def place_existing_instance_plans(desired_instances, existing_instance_models)
30
64
  instance_plans = []
31
65
  # create existing instance plans with network plans that use specified static IPs
@@ -231,6 +265,10 @@ module Bosh
231
265
  def instance_name(existing_instance_model)
232
266
  "#{existing_instance_model.job}/#{existing_instance_model.index}"
233
267
  end
268
+
269
+ def ignored_instances_are_obsolete?(instance_plans)
270
+ instance_plans.select{ |i| i.obsolete? && i.should_be_ignored? }.any?
271
+ end
234
272
  end
235
273
  end
236
274
  end