bosh-director 1.3160.0 → 1.3163.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (195) hide show
  1. checksums.yaml +4 -4
  2. data/bin/bosh-director-worker +2 -14
  3. data/db/migrations/director/20150513225143_ip_addresses.rb +11 -0
  4. data/db/migrations/director/20150702004608_add_links.rb +8 -0
  5. data/db/migrations/director/20150708231924_add_link_spec.rb +7 -0
  6. data/db/migrations/director/20150724183256_add_debugging_to_ip_addresses.rb +8 -0
  7. data/db/migrations/director/20150730225029_add_uuid_to_instances.rb +16 -0
  8. data/db/migrations/director/20150803215805_add_availabililty_zone_and_cloud_properties_to_instances.rb +8 -0
  9. data/db/migrations/director/20150804211419_add_compilation_flag_to_instance.rb +7 -0
  10. data/db/migrations/director/20150918003455_add_bootstrap_node_to_instance.rb +7 -0
  11. data/db/migrations/director/20151008232214_add_dns_records.rb +7 -0
  12. data/db/migrations/director/20151015172551_add_orphan_disks_and_snapshots.rb +29 -0
  13. data/db/migrations/director/20151030222853_add_templates_to_instance.rb +10 -0
  14. data/db/migrations/director/20151031001039_add_spec_to_instance.rb +19 -0
  15. data/db/migrations/director/20151109190602_rename_orphan_columns.rb +13 -0
  16. data/lib/bosh/director.rb +19 -9
  17. data/lib/bosh/director/agent_client.rb +0 -17
  18. data/lib/bosh/director/api/cloud_config_manager.rb +7 -5
  19. data/lib/bosh/director/api/controllers/base_controller.rb +3 -2
  20. data/lib/bosh/director/api/controllers/cleanup_controller.rb +15 -0
  21. data/lib/bosh/director/api/controllers/deployments_controller.rb +38 -26
  22. data/lib/bosh/director/api/controllers/disks_controller.rb +20 -0
  23. data/lib/bosh/director/api/controllers/info_controller.rb +2 -2
  24. data/lib/bosh/director/api/controllers/releases_controller.rb +1 -16
  25. data/lib/bosh/director/api/controllers/stemcells_controller.rb +1 -9
  26. data/lib/bosh/director/api/deployment_manager.rb +2 -1
  27. data/lib/bosh/director/api/instance_lookup.rb +17 -0
  28. data/lib/bosh/director/api/instance_manager.rb +20 -10
  29. data/lib/bosh/director/api/release_manager.rb +28 -8
  30. data/lib/bosh/director/api/resurrector_manager.rb +9 -2
  31. data/lib/bosh/director/api/route_configuration.rb +2 -0
  32. data/lib/bosh/director/api/snapshot_manager.rb +9 -5
  33. data/lib/bosh/director/api/stemcell_manager.rb +50 -0
  34. data/lib/bosh/director/app.rb +1 -1
  35. data/lib/bosh/director/cloudcheck_helper.rb +119 -132
  36. data/lib/bosh/director/compile_task.rb +1 -1
  37. data/lib/bosh/director/compile_task_generator.rb +2 -2
  38. data/lib/bosh/director/config.rb +21 -12
  39. data/lib/bosh/director/deployment_deleter.rb +69 -0
  40. data/lib/bosh/director/deployment_plan.rb +35 -4
  41. data/lib/bosh/director/deployment_plan/agent_state_migrator.rb +47 -0
  42. data/lib/bosh/director/deployment_plan/assembler.rb +115 -241
  43. data/lib/bosh/director/deployment_plan/availability_zone.rb +27 -0
  44. data/lib/bosh/director/deployment_plan/cloud_manifest_parser.rb +144 -35
  45. data/lib/bosh/director/deployment_plan/compilation_config.rb +21 -19
  46. data/lib/bosh/director/deployment_plan/compilation_instance_pool.rb +169 -0
  47. data/lib/bosh/director/deployment_plan/deployment_repo.rb +4 -8
  48. data/lib/bosh/director/deployment_plan/deployment_spec_parser.rb +13 -1
  49. data/lib/bosh/director/deployment_plan/deployment_validator.rb +17 -0
  50. data/lib/bosh/director/deployment_plan/desired_instance.rb +15 -0
  51. data/lib/bosh/director/deployment_plan/{disk_pool.rb → disk_type.rb} +14 -19
  52. data/lib/bosh/director/deployment_plan/dynamic_network.rb +105 -53
  53. data/lib/bosh/director/deployment_plan/dynamic_network_subnet.rb +13 -0
  54. data/lib/bosh/director/deployment_plan/env.rb +18 -0
  55. data/lib/bosh/director/deployment_plan/global_network_resolver.rb +77 -0
  56. data/lib/bosh/director/deployment_plan/instance.rb +222 -390
  57. data/lib/bosh/director/deployment_plan/instance_network_reservations.rb +71 -0
  58. data/lib/bosh/director/deployment_plan/instance_plan.rb +336 -0
  59. data/lib/bosh/director/deployment_plan/instance_plan_factory.rb +54 -0
  60. data/lib/bosh/director/deployment_plan/instance_plan_sorter.rb +61 -0
  61. data/lib/bosh/director/deployment_plan/instance_planner.rb +101 -0
  62. data/lib/bosh/director/deployment_plan/instance_repository.rb +36 -0
  63. data/lib/bosh/director/deployment_plan/instance_spec.rb +154 -0
  64. data/lib/bosh/director/deployment_plan/ip_provider/database_ip_repo.rb +136 -0
  65. data/lib/bosh/director/deployment_plan/ip_provider/in_memory_ip_repo.rb +81 -0
  66. data/lib/bosh/director/deployment_plan/ip_provider/ip_provider.rb +153 -0
  67. data/lib/bosh/director/deployment_plan/ip_provider/ip_provider_factory.rb +22 -0
  68. data/lib/bosh/director/deployment_plan/job.rb +116 -53
  69. data/lib/bosh/director/deployment_plan/job_availability_zone_parser.rb +49 -0
  70. data/lib/bosh/director/deployment_plan/job_migrator.rb +90 -0
  71. data/lib/bosh/director/deployment_plan/job_network.rb +42 -0
  72. data/lib/bosh/director/deployment_plan/job_network_parser.rb +118 -0
  73. data/lib/bosh/director/deployment_plan/job_spec_parser.rb +123 -126
  74. data/lib/bosh/director/deployment_plan/links/link.rb +30 -0
  75. data/lib/bosh/director/deployment_plan/links/link_lookup.rb +66 -0
  76. data/lib/bosh/director/deployment_plan/links/link_path.rb +27 -0
  77. data/lib/bosh/director/deployment_plan/links/links_resolver.rb +70 -0
  78. data/lib/bosh/director/deployment_plan/links/template_link.rb +21 -0
  79. data/lib/bosh/director/deployment_plan/manifest_migrator.rb +3 -17
  80. data/lib/bosh/director/deployment_plan/manifest_validator.rb +46 -0
  81. data/lib/bosh/director/deployment_plan/manual_network.rb +70 -97
  82. data/lib/bosh/director/deployment_plan/manual_network_subnet.rb +148 -0
  83. data/lib/bosh/director/deployment_plan/network.rb +50 -39
  84. data/lib/bosh/director/deployment_plan/network_planner.rb +4 -0
  85. data/lib/bosh/director/deployment_plan/network_planner/plan.rb +26 -0
  86. data/lib/bosh/director/deployment_plan/network_planner/planner.rb +21 -0
  87. data/lib/bosh/director/deployment_plan/network_planner/reservation_reconciler.rb +81 -0
  88. data/lib/bosh/director/deployment_plan/network_planner/vip_static_ips_planner.rb +50 -0
  89. data/lib/bosh/director/deployment_plan/network_settings.rb +65 -0
  90. data/lib/bosh/director/deployment_plan/options/skip_drain.rb +7 -0
  91. data/lib/bosh/director/deployment_plan/package_validator.rb +79 -0
  92. data/lib/bosh/director/deployment_plan/placement_planner.rb +8 -0
  93. data/lib/bosh/director/deployment_plan/placement_planner/availability_zone_picker.rb +90 -0
  94. data/lib/bosh/director/deployment_plan/placement_planner/bruteforce_ip_allocation.rb +124 -0
  95. data/lib/bosh/director/deployment_plan/placement_planner/index_assigner.rb +32 -0
  96. data/lib/bosh/director/deployment_plan/placement_planner/networks_to_static_ips.rb +125 -0
  97. data/lib/bosh/director/deployment_plan/placement_planner/placed_desired_instances.rb +40 -0
  98. data/lib/bosh/director/deployment_plan/placement_planner/plan.rb +42 -0
  99. data/lib/bosh/director/deployment_plan/placement_planner/static_ips_availability_zone_picker.rb +237 -0
  100. data/lib/bosh/director/deployment_plan/placement_planner/unplaced_existing_instances.rb +53 -0
  101. data/lib/bosh/director/deployment_plan/planner.rb +186 -74
  102. data/lib/bosh/director/deployment_plan/planner_factory.rb +30 -147
  103. data/lib/bosh/director/deployment_plan/release_version.rb +3 -3
  104. data/lib/bosh/director/deployment_plan/resource_pool.rb +2 -174
  105. data/lib/bosh/director/deployment_plan/stemcell.rb +57 -14
  106. data/lib/bosh/director/deployment_plan/steps/package_compile_step.rb +28 -135
  107. data/lib/bosh/director/deployment_plan/steps/update_step.rb +23 -44
  108. data/lib/bosh/director/deployment_plan/template.rb +15 -4
  109. data/lib/bosh/director/deployment_plan/vip_network.rb +14 -42
  110. data/lib/bosh/director/deployment_plan/vm.rb +1 -99
  111. data/lib/bosh/director/deployment_plan/vm_type.rb +27 -0
  112. data/lib/bosh/director/disk_manager.rb +268 -0
  113. data/lib/bosh/director/dns/canonicalizer.rb +28 -0
  114. data/lib/bosh/director/dns/dns_manager.rb +163 -0
  115. data/lib/bosh/director/dns/local_dns_repo.rb +20 -0
  116. data/lib/bosh/director/dns/powerdns.rb +170 -0
  117. data/lib/bosh/director/errand/job_manager.rb +18 -29
  118. data/lib/bosh/director/error_ignorer.rb +16 -0
  119. data/lib/bosh/director/errors.rb +51 -20
  120. data/lib/bosh/director/event_log.rb +6 -0
  121. data/lib/bosh/director/instance_deleter.rb +53 -81
  122. data/lib/bosh/director/instance_reuser.rb +89 -0
  123. data/lib/bosh/director/instance_updater.rb +139 -281
  124. data/lib/bosh/director/instance_updater/preparer.rb +8 -5
  125. data/lib/bosh/director/instance_updater/state_applier.rb +21 -0
  126. data/lib/bosh/director/ip_util.rb +46 -26
  127. data/lib/bosh/director/job_renderer.rb +22 -10
  128. data/lib/bosh/director/job_runner.rb +1 -4
  129. data/lib/bosh/director/job_updater.rb +47 -35
  130. data/lib/bosh/director/job_updater_factory.rb +5 -4
  131. data/lib/bosh/director/jobs/base_job.rb +8 -0
  132. data/lib/bosh/director/jobs/cleanup_artifacts.rb +93 -0
  133. data/lib/bosh/director/jobs/delete_deployment.rb +10 -154
  134. data/lib/bosh/director/jobs/delete_deployment_snapshots.rb +1 -1
  135. data/lib/bosh/director/jobs/delete_orphan_disks.rb +44 -0
  136. data/lib/bosh/director/jobs/delete_release.rb +19 -196
  137. data/lib/bosh/director/jobs/delete_stemcell.rb +10 -76
  138. data/lib/bosh/director/jobs/export_release.rb +41 -121
  139. data/lib/bosh/director/jobs/fetch_logs.rb +0 -6
  140. data/lib/bosh/director/jobs/helpers.rb +10 -0
  141. data/lib/bosh/director/jobs/helpers/blob_deleter.rb +24 -0
  142. data/lib/bosh/director/jobs/helpers/compiled_package_deleter.rb +24 -0
  143. data/lib/bosh/director/jobs/helpers/name_version_release_deleter.rb +48 -0
  144. data/lib/bosh/director/jobs/helpers/package_deleter.rb +33 -0
  145. data/lib/bosh/director/jobs/helpers/release_deleter.rb +52 -0
  146. data/lib/bosh/director/jobs/helpers/release_version_deleter.rb +115 -0
  147. data/lib/bosh/director/jobs/helpers/releases_to_delete_picker.rb +31 -0
  148. data/lib/bosh/director/jobs/helpers/stemcell_deleter.rb +61 -0
  149. data/lib/bosh/director/jobs/helpers/stemcells_to_delete_picker.rb +30 -0
  150. data/lib/bosh/director/jobs/helpers/template_deleter.rb +20 -0
  151. data/lib/bosh/director/jobs/release/release_job.rb +18 -7
  152. data/lib/bosh/director/jobs/run_errand.rb +57 -36
  153. data/lib/bosh/director/jobs/scheduled_orphan_cleanup.rb +46 -0
  154. data/lib/bosh/director/jobs/ssh.rb +50 -17
  155. data/lib/bosh/director/jobs/update_deployment.rb +29 -11
  156. data/lib/bosh/director/jobs/update_release.rb +25 -4
  157. data/lib/bosh/director/jobs/vm_state.rb +23 -32
  158. data/lib/bosh/director/lock.rb +13 -8
  159. data/lib/bosh/director/logs_fetcher.rb +1 -1
  160. data/lib/bosh/director/models.rb +3 -0
  161. data/lib/bosh/director/models/compiled_package.rb +3 -3
  162. data/lib/bosh/director/models/deployment.rb +10 -0
  163. data/lib/bosh/director/models/instance.rb +77 -1
  164. data/lib/bosh/director/models/ip_address.rb +26 -0
  165. data/lib/bosh/director/models/orphan_disk.rb +23 -0
  166. data/lib/bosh/director/models/orphan_snapshot.rb +14 -0
  167. data/lib/bosh/director/models/template.rb +32 -9
  168. data/lib/bosh/director/models/vm.rb +5 -8
  169. data/lib/bosh/director/network_reservation.rb +69 -99
  170. data/lib/bosh/director/problem_handlers/inactive_disk.rb +5 -20
  171. data/lib/bosh/director/problem_handlers/missing_disk.rb +2 -13
  172. data/lib/bosh/director/problem_resolver.rb +2 -2
  173. data/lib/bosh/director/problem_scanner/vm_scan_stage.rb +2 -21
  174. data/lib/bosh/director/scheduler.rb +23 -6
  175. data/lib/bosh/director/{instance_updater/stopper.rb → stopper.rb} +24 -18
  176. data/lib/bosh/director/tagged_logger.rb +30 -0
  177. data/lib/bosh/director/transactor.rb +9 -0
  178. data/lib/bosh/director/version.rb +1 -1
  179. data/lib/bosh/director/vm_creator.rb +91 -19
  180. data/lib/bosh/director/vm_deleter.rb +25 -0
  181. data/lib/bosh/director/vm_recreator.rb +15 -0
  182. data/lib/cloud/dummy.rb +381 -94
  183. metadata +110 -30
  184. data/lib/bosh/director/deployment_plan/dns_binder.rb +0 -45
  185. data/lib/bosh/director/deployment_plan/instance_vm_binder.rb +0 -37
  186. data/lib/bosh/director/deployment_plan/network_subnet.rb +0 -166
  187. data/lib/bosh/director/deployment_plan/resource_pools.rb +0 -68
  188. data/lib/bosh/director/dns_helper.rb +0 -223
  189. data/lib/bosh/director/instance_updater/network_updater.rb +0 -110
  190. data/lib/bosh/director/instance_updater/vm_updater.rb +0 -189
  191. data/lib/bosh/director/problem_handlers/out_of_sync_vm.rb +0 -64
  192. data/lib/bosh/director/problem_handlers/unbound_instance_vm.rb +0 -85
  193. data/lib/bosh/director/resource_pool_updater.rb +0 -174
  194. data/lib/bosh/director/vm_data.rb +0 -63
  195. data/lib/bosh/director/vm_reuser.rb +0 -63
@@ -0,0 +1,89 @@
1
+ module Bosh::Director
2
+ class NilInstanceError < ArgumentError; end
3
+
4
+ # A class for maintaining Instance objects, making reusing Instances easier.
5
+ class InstanceReuser
6
+ def initialize
7
+ @idle_instances_by_stemcell = {}
8
+ @in_use_instances_by_stemcell = {}
9
+ @mutex = Mutex.new
10
+ end
11
+
12
+ # Adds an instance's information to the pool of VMs that can be reused.
13
+ # @param [DeploymentPlan::Instance] The instance for the new VM.
14
+ def add_in_use_instance(instance, stemcell)
15
+ raise NilInstanceError if instance.nil?
16
+ @mutex.synchronize do
17
+ @in_use_instances_by_stemcell[stemcell] ||= []
18
+ @in_use_instances_by_stemcell[stemcell] << instance
19
+ end
20
+ end
21
+
22
+ # Returns the instance of a VM that is not in use and can be reused.
23
+ # @param [Models::Stemcell] stemcell The stemcell that the VM must be running.
24
+ # @return [DeploymentPlan::Instance] The instance for an existing unused VM, if one exists. Otherwise, nil.
25
+ def get_instance(stemcell)
26
+ @mutex.synchronize do
27
+ return nil if @idle_instances_by_stemcell[stemcell].nil?
28
+ instance = @idle_instances_by_stemcell[stemcell].pop
29
+ return nil if instance.nil?
30
+ @in_use_instances_by_stemcell[stemcell] ||= []
31
+ @in_use_instances_by_stemcell[stemcell] << instance
32
+ return instance
33
+ end
34
+ end
35
+
36
+ def release_instance(instance)
37
+ raise NilInstanceError if instance.nil?
38
+ @mutex.synchronize do
39
+ release_without_lock(instance)
40
+ end
41
+ end
42
+
43
+ def remove_instance(instance)
44
+ raise NilInstanceError if instance.nil?
45
+ @mutex.synchronize do
46
+ release_without_lock(instance)
47
+ @idle_instances_by_stemcell.each_value do |vms|
48
+ vms.each do |v|
49
+ vms.delete(v) if instance == v
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ # Gets the total number of compilation instances created with a given stemcell.
56
+ # @param [Models::Stemcell] stemcell The stemcell the VMs are running.
57
+ # @return [Integer] The number of instances running a given stemcell.
58
+ def get_num_instances(stemcell)
59
+ @mutex.synchronize do
60
+ idle_count = @idle_instances_by_stemcell[stemcell].nil? ? 0 : @idle_instances_by_stemcell[stemcell].size
61
+ in_use_count = @in_use_instances_by_stemcell[stemcell].nil? ? 0 : @in_use_instances_by_stemcell[stemcell].size
62
+ idle_count + in_use_count
63
+ end
64
+ end
65
+
66
+ # An iterator for all compilation VMs on all stemcells.
67
+ # @yield [DeploymentPlan::Instance] yields each instance in InstanceReuser.
68
+ def each
69
+ all_vms = (@idle_instances_by_stemcell.values + @in_use_instances_by_stemcell.values).flatten
70
+ all_vms.each do |vm|
71
+ yield vm
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def release_without_lock(instance)
78
+ @in_use_instances_by_stemcell.each do |stemcell, vms|
79
+ vms.each do |v|
80
+ if instance == v
81
+ vms.delete(v)
82
+ @idle_instances_by_stemcell[stemcell] ||= []
83
+ @idle_instances_by_stemcell[stemcell] << instance
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -2,283 +2,142 @@ require 'bosh/director/rendered_job_templates_cleaner'
2
2
 
3
3
  module Bosh::Director
4
4
  class InstanceUpdater
5
- include DnsHelper
6
-
7
5
  WATCH_INTERVALS = 10
6
+ MAX_RECREATE_ATTEMPTS = 3
8
7
 
9
8
  attr_reader :current_state
10
9
 
11
- # @params [DeploymentPlan::Instance] instance
12
- def initialize(instance, event_log_task, job_renderer)
13
- @instance = instance
14
- @event_log_task = event_log_task
15
- @job_renderer = job_renderer
16
-
17
- @cloud = Config.cloud
18
- @logger = Config.logger
19
- @blobstore = App.instance.blobstores.blobstore
20
-
21
- @job = instance.job
22
- @target_state = @instance.state
23
-
24
- @deployment_plan = @job.deployment
25
- @resource_pool = @job.resource_pool
26
- @update_config = @job.update
27
-
28
- @vm = @instance.model.vm
29
-
10
+ def self.new_instance_updater(ip_provider)
11
+ logger = Config.logger
12
+ cloud = Config.cloud
13
+ vm_deleter = VmDeleter.new(cloud, logger)
14
+ disk_manager = DiskManager.new(cloud, logger)
15
+ job_renderer = JobRenderer.create
16
+ vm_creator = VmCreator.new(cloud, logger, vm_deleter, disk_manager, job_renderer)
17
+ vm_recreator = VmRecreator.new(vm_creator, vm_deleter)
18
+ dns_manager = DnsManager.create
19
+ new(
20
+ cloud,
21
+ logger,
22
+ ip_provider,
23
+ App.instance.blobstores.blobstore,
24
+ vm_deleter,
25
+ vm_creator,
26
+ dns_manager,
27
+ disk_manager,
28
+ vm_recreator
29
+ )
30
+ end
31
+
32
+ def initialize(cloud, logger, ip_provider, blobstore, vm_deleter, vm_creator, dns_manager, disk_manager, vm_recreator)
33
+ @cloud = cloud
34
+ @logger = logger
35
+ @blobstore = blobstore
36
+ @vm_deleter = vm_deleter
37
+ @vm_creator = vm_creator
38
+ @dns_manager = dns_manager
39
+ @disk_manager = disk_manager
40
+ @ip_provider = ip_provider
30
41
  @current_state = {}
31
-
32
- @agent = AgentClient.with_defaults(@vm.agent_id)
42
+ @vm_recreator = vm_recreator
33
43
  end
34
44
 
35
- def report_progress(num_steps)
36
- @event_log_task.advance(100.0 / num_steps)
37
- end
45
+ def update(instance_plan, options = {})
46
+ instance = instance_plan.instance
47
+ @logger.info("Updating instance #{instance}, changes: #{instance_plan.changes.to_a.join(', ').inspect}")
38
48
 
39
- def update_steps(options = {})
40
- steps = []
41
49
  @canary = options.fetch(:canary, false)
42
50
 
43
51
  # Optimization to only update DNS if nothing else changed.
44
- if dns_change_only?
45
- steps << proc { update_dns }
46
- return steps
52
+ if dns_change_only?(instance_plan)
53
+ @logger.debug('Only change is DNS configuration')
54
+ update_dns(instance_plan)
55
+ return
47
56
  end
48
57
 
49
- steps << proc { Preparer.new(@instance, agent, @logger).prepare }
50
- steps << proc { stop }
51
- steps << proc { take_snapshot }
52
-
53
- if @target_state == "detached"
54
- steps << proc { vm_updater.detach }
55
- return steps
56
- end
58
+ unless instance_plan.currently_detached?
59
+ Preparer.new(instance_plan, agent(instance), @logger).prepare
57
60
 
58
- steps << proc { recreate_vm(nil) }
59
- steps << proc { update_networks }
60
- steps << proc { update_dns }
61
- steps << proc { update_persistent_disk }
62
- steps << proc { update_settings }
63
-
64
- if !trusted_certs_change_only?
65
- steps << proc {
66
- VmMetadataUpdater.build.update(@vm, {})
67
- apply_state(@instance.spec)
68
- RenderedJobTemplatesCleaner.new(@instance.model, @blobstore, @logger).clean
69
- }
61
+ stop(instance_plan)
62
+ take_snapshot(instance)
70
63
  end
71
64
 
72
- if need_start?
73
- steps << proc { run_pre_start_scripts }
74
- steps << proc { start! }
65
+ if instance.state == 'detached'
66
+ @logger.info("Detaching instance #{instance}")
67
+ unless instance_plan.currently_detached?
68
+ @disk_manager.unmount_disk_for(instance_plan)
69
+ @vm_deleter.delete_for_instance_plan(instance_plan)
70
+ end
71
+ release_obsolete_ips(instance_plan)
72
+ instance.update_state
73
+ return
75
74
  end
76
75
 
77
- steps << proc { wait_until_running }
78
-
79
- steps
80
- end
81
-
82
- def update(options = {})
83
- steps = update_steps(options)
84
-
85
- @logger.info("Updating instance #{@instance}, changes: #{@instance.changes.to_a.join(', ')}")
86
-
87
- steps.each do |step|
88
- step.call
89
- report_progress(steps.length)
76
+ recreated = false
77
+ if needs_recreate?(instance_plan)
78
+ @logger.debug('Failed to update in place. Recreating VM')
79
+ @disk_manager.unmount_disk_for(instance_plan)
80
+ @vm_recreator.recreate_vm(instance_plan, nil)
81
+ recreated = true
90
82
  end
91
83
 
92
- if @target_state == "started" && current_state["job_state"] != "running"
93
- raise AgentJobNotRunning, "`#{@instance}' is not running after update"
94
- end
84
+ release_obsolete_ips(instance_plan)
95
85
 
96
- if @target_state == "stopped" && current_state["job_state"] == "running"
97
- raise AgentJobNotStopped, "`#{@instance}' is still running despite the stop command"
98
- end
99
- end
86
+ update_dns(instance_plan)
87
+ @disk_manager.update_persistent_disk(instance_plan, @vm_recreator)
100
88
 
101
- # Watch times don't include the get_state roundtrip time, so effective
102
- # max watch time is roughly:
103
- # max_watch_time + N_WATCH_INTERVALS * avg_roundtrip_time
104
- def wait_until_running
105
- watch_schedule(min_watch_time, max_watch_time).each do |watch_time|
106
- sleep_time = watch_time.to_f / 1000
107
- @logger.info("Waiting for #{sleep_time} seconds to check #{@instance} status")
108
- sleep(sleep_time)
109
- @logger.info("Checking if #{@instance} has been updated after #{sleep_time} seconds")
110
-
111
- @current_state = agent.get_state
112
-
113
- if @target_state == "started"
114
- break if current_state["job_state"] == "running"
115
- elsif @target_state == "stopped"
116
- break if current_state["job_state"] != "running"
89
+ unless recreated
90
+ if instance.trusted_certs_changed?
91
+ @logger.debug('Updating trusted certs')
92
+ instance.update_trusted_certs
117
93
  end
118
94
  end
119
- end
120
-
121
- def run_pre_start_scripts
122
- @agent.run_script("pre-start", {})
123
- end
124
-
125
- def start!
126
- agent.start
127
- end
128
-
129
- def need_start?
130
- @target_state == 'started'
131
- end
132
-
133
- def dns_change_only?
134
- @instance.changes.include?(:dns) && @instance.changes.size == 1
135
- end
136
-
137
- def trusted_certs_change_only?
138
- @instance.changes.include?(:trusted_certs) && @instance.changes.size == 1
139
- end
140
-
141
- def stop
142
- skip_drain = @deployment_plan.skip_drain_for_job?(@job.name)
143
- stopper = Stopper.new(@instance, agent, @target_state, skip_drain, Config, @logger)
144
- stopper.stop
145
- end
146
-
147
- def take_snapshot
148
- Api::SnapshotManager.take_snapshot(@instance.model, clean: true)
149
- end
150
-
151
- def delete_snapshots(disk)
152
- Api::SnapshotManager.delete_snapshots(disk.snapshots)
153
- end
154
-
155
- def apply_state(state)
156
- @vm.update(:apply_spec => state)
157
- agent.apply(state)
158
- end
159
-
160
- # Retrieve list of mounted disks from the agent
161
- # @return [Array<String>] list of disk CIDs
162
- def disk_info
163
- return @disk_list if @disk_list
164
-
165
- begin
166
- @disk_list = agent.list_disk
167
- rescue RuntimeError
168
- # old agents don't support list_disk rpc
169
- [@instance.persistent_disk_cid]
170
- end
171
- end
172
95
 
173
- def delete_unused_disk(disk)
174
- @cloud.delete_disk(disk.disk_cid)
175
- disk.destroy
176
- end
96
+ cleaner = RenderedJobTemplatesCleaner.new(instance.model, @blobstore, @logger)
97
+ InstanceUpdater::StateApplier.new(instance_plan, agent(instance), cleaner).apply
177
98
 
178
- def delete_mounted_disk(disk)
179
- disk_cid = disk.disk_cid
180
- vm_cid = @vm.cid
99
+ instance.update_state
181
100
 
182
- # Unmount the disk only if disk is known by the agent
183
- if agent && disk_info.include?(disk_cid)
184
- agent.unmount_disk(disk_cid)
185
- end
101
+ wait_until_running(instance_plan)
186
102
 
187
- begin
188
- @cloud.detach_disk(vm_cid, disk_cid) if vm_cid
189
- rescue Bosh::Clouds::DiskNotAttached
190
- if disk.active
191
- raise CloudDiskNotAttached,
192
- "`#{@instance}' VM should have persistent disk attached " +
193
- "but it doesn't (according to CPI)"
194
- end
103
+ if instance.state == "started" && current_state["job_state"] != "running"
104
+ raise AgentJobNotRunning, "`#{instance}' is not running after update"
195
105
  end
196
106
 
197
- delete_snapshots(disk)
198
-
199
- begin
200
- @cloud.delete_disk(disk_cid)
201
- rescue Bosh::Clouds::DiskNotFound
202
- if disk.active
203
- raise CloudDiskMissing,
204
- "Disk `#{disk_cid}' is missing according to CPI but marked " +
205
- "as active in DB"
206
- end
107
+ if instance.state == "stopped" && current_state["job_state"] == "running"
108
+ raise AgentJobNotStopped, "`#{instance}' is still running despite the stop command"
207
109
  end
208
-
209
- disk.destroy
210
110
  end
211
111
 
212
- def update_dns
213
- return unless @instance.dns_changed?
112
+ private
214
113
 
215
- domain = @deployment_plan.dns_domain
216
- @instance.dns_record_info.each do |record_name, ip_address|
217
- @logger.info("Updating DNS for: #{record_name} to #{ip_address}")
218
- update_dns_a_record(domain, record_name, ip_address)
219
- update_dns_ptr_record(record_name, ip_address)
114
+ def release_obsolete_ips(instance_plan)
115
+ instance_plan.network_plans
116
+ .select(&:obsolete?)
117
+ .each do |network_plan|
118
+ reservation = network_plan.reservation
119
+ @ip_provider.release(reservation)
220
120
  end
221
- flush_dns_cache
121
+ instance_plan.release_obsolete_network_plans
222
122
  end
223
123
 
224
- def recreate_vm(new_disk_cid)
225
- @vm, @agent = vm_updater.update(new_disk_cid)
124
+ def stop(instance_plan)
125
+ instance = instance_plan.instance
126
+ stopper = Stopper.new(instance_plan, instance.state, Config, @logger)
127
+ stopper.stop
226
128
  end
227
129
 
228
- # Synchronizes persistent_disks with the agent.
229
- # (Currently assumes that we only have 1 persistent disk.)
230
- # @return [void]
231
- def check_persistent_disk
232
- return if @instance.model.persistent_disks.empty?
233
- agent_disk_cid = disk_info.first
234
-
235
- if agent_disk_cid != @instance.model.persistent_disk_cid
236
- raise AgentDiskOutOfSync,
237
- "`#{@instance}' has invalid disks: agent reports " +
238
- "`#{agent_disk_cid}' while director record shows " +
239
- "`#{@instance.model.persistent_disk_cid}'"
240
- end
241
-
242
- @instance.model.persistent_disks.each do |disk|
243
- unless disk.active
244
- @logger.warn("`#{@instance}' has inactive disk #{disk.disk_cid}")
245
- end
246
- end
130
+ def take_snapshot(instance)
131
+ Api::SnapshotManager.take_snapshot(instance.model, clean: true)
247
132
  end
248
133
 
249
- def update_persistent_disk
250
- vm_updater.attach_missing_disk
251
- check_persistent_disk
134
+ def update_dns(instance_plan)
135
+ instance = instance_plan.instance
252
136
 
253
- disk = nil
254
- return unless @instance.persistent_disk_changed?
137
+ return unless instance_plan.dns_changed?
255
138
 
256
- old_disk = @instance.model.persistent_disk
257
-
258
- if @job.persistent_disk_pool && @job.persistent_disk_pool.disk_size > 0
259
- disk = create_disk
260
- attach_disk(disk)
261
- mount_and_migrate_disk(disk, old_disk)
262
- end
263
-
264
- @instance.model.db.transaction do
265
- old_disk.update(:active => false) if old_disk
266
- disk.update(:active => true) if disk
267
- end
268
-
269
- delete_mounted_disk(old_disk) if old_disk
270
- end
271
-
272
- def update_networks
273
- network_updater = NetworkUpdater.new(@instance, @vm, agent, vm_updater, @cloud, @logger)
274
- @vm, @agent = network_updater.update
275
- end
276
-
277
- def update_settings
278
- if @instance.trusted_certs_changed?
279
- @agent.update_settings(Config.trusted_certs)
280
- @vm.update(:trusted_certs_sha1 => Digest::SHA1.hexdigest(Config.trusted_certs))
281
- end
139
+ @dns_manager.update_dns_record_for_instance(instance.model, instance_plan.network_settings.dns_record_info)
140
+ @dns_manager.flush_dns_cache
282
141
  end
283
142
 
284
143
  # Returns an array of wait times distributed
@@ -299,70 +158,69 @@ module Bosh::Director
299
158
  [min_watch_time] + ([step] * (delta / step).floor)
300
159
  end
301
160
 
302
- def min_watch_time
303
- canary? ? @update_config.min_canary_watch_time : @update_config.min_update_watch_time
161
+ def get_min_watch_time(update_config)
162
+ canary? ? update_config.min_canary_watch_time : update_config.min_update_watch_time
304
163
  end
305
164
 
306
- def max_watch_time
307
- canary? ? @update_config.max_canary_watch_time : @update_config.max_update_watch_time
165
+ def get_max_watch_time(update_config)
166
+ canary? ? update_config.max_canary_watch_time : update_config.max_update_watch_time
308
167
  end
309
168
 
310
169
  def canary?
311
170
  @canary
312
171
  end
313
172
 
314
- attr_reader :agent
315
-
316
- def vm_updater
317
- # Do not memoize to avoid caching same VM and agent
318
- # which could be replaced after updating a VM
319
- VmUpdater.new(@instance, @vm, agent, @job_renderer, @cloud, 3, @logger)
173
+ def dns_change_only?(instance_plan)
174
+ instance_plan.changes.include?(:dns) && instance_plan.changes.size == 1
320
175
  end
321
176
 
322
- private
177
+ # Watch times don't include the get_state roundtrip time, so effective
178
+ # max watch time is roughly:
179
+ # max_watch_time + N_WATCH_INTERVALS * avg_roundtrip_time
180
+ def wait_until_running(instance_plan)
181
+ instance = instance_plan.instance
182
+ job = instance_plan.desired_instance.job
183
+ min_watch_time = get_min_watch_time(job.update)
184
+ max_watch_time = get_max_watch_time(job.update)
185
+ watch_schedule(min_watch_time, max_watch_time).each do |watch_time|
186
+ sleep_time = watch_time.to_f / 1000
187
+ @logger.info("Waiting for #{sleep_time} seconds to check #{instance} status")
188
+ sleep(sleep_time)
189
+ @logger.info("Checking if #{instance} has been updated after #{sleep_time} seconds")
323
190
 
324
- def create_disk
325
- disk_size = @job.persistent_disk_pool.disk_size
326
- cloud_properties = @job.persistent_disk_pool.cloud_properties
327
-
328
- disk = nil
329
- @instance.model.db.transaction do
330
- disk_cid = @cloud.create_disk(disk_size, cloud_properties, @vm.cid)
331
- disk = Models::PersistentDisk.create(
332
- disk_cid: disk_cid,
333
- active: false,
334
- instance_id: @instance.model.id,
335
- size: disk_size,
336
- cloud_properties: cloud_properties,
337
- )
191
+ @current_state = agent(instance).get_state
192
+
193
+ if instance.state == "started"
194
+ break if current_state["job_state"] == "running"
195
+ elsif instance.state == "stopped"
196
+ break if current_state["job_state"] != "running"
197
+ end
338
198
  end
339
- disk
340
199
  end
341
200
 
342
- def attach_disk(disk)
343
- @cloud.attach_disk(@vm.cid, disk.disk_cid)
344
- rescue Bosh::Clouds::NoDiskSpace => e
345
- if e.ok_to_retry
346
- @logger.warn('Retrying attach disk operation after persistent disk update failed')
347
- recreate_vm(disk.disk_cid)
348
- begin
349
- @cloud.attach_disk(@vm.cid, disk.disk_cid)
350
- rescue
351
- delete_unused_disk(disk)
352
- raise
353
- end
354
- else
355
- delete_unused_disk(disk)
356
- raise
201
+ def needs_recreate?(instance_plan)
202
+ instance = instance_plan.instance
203
+
204
+ if instance_plan.needs_shutting_down?
205
+ @logger.debug('VM needs to be shutdown before it can be updated.')
206
+ return true
357
207
  end
208
+
209
+ if instance.cloud_properties_changed?
210
+ @logger.debug('Cloud Properties have changed. Recreating VM')
211
+ return true
212
+ end
213
+
214
+ if instance_plan.networks_changed?
215
+ @logger.debug('Networks have changed. Recreating VM')
216
+ return true
217
+ end
218
+
219
+ false
358
220
  end
359
221
 
360
- def mount_and_migrate_disk(new_disk, old_disk)
361
- agent.mount_disk(new_disk.disk_cid)
362
- agent.migrate_disk(old_disk.disk_cid, new_disk.disk_cid) if old_disk
363
- rescue
364
- delete_mounted_disk(new_disk)
365
- raise
222
+ def agent(instance)
223
+ AgentClient.with_vm(instance.model.vm)
366
224
  end
367
225
  end
368
226
  end