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.
- checksums.yaml +4 -4
- data/bin/bosh-director-worker +2 -14
- data/db/migrations/director/20150513225143_ip_addresses.rb +11 -0
- data/db/migrations/director/20150702004608_add_links.rb +8 -0
- data/db/migrations/director/20150708231924_add_link_spec.rb +7 -0
- data/db/migrations/director/20150724183256_add_debugging_to_ip_addresses.rb +8 -0
- data/db/migrations/director/20150730225029_add_uuid_to_instances.rb +16 -0
- data/db/migrations/director/20150803215805_add_availabililty_zone_and_cloud_properties_to_instances.rb +8 -0
- data/db/migrations/director/20150804211419_add_compilation_flag_to_instance.rb +7 -0
- data/db/migrations/director/20150918003455_add_bootstrap_node_to_instance.rb +7 -0
- data/db/migrations/director/20151008232214_add_dns_records.rb +7 -0
- data/db/migrations/director/20151015172551_add_orphan_disks_and_snapshots.rb +29 -0
- data/db/migrations/director/20151030222853_add_templates_to_instance.rb +10 -0
- data/db/migrations/director/20151031001039_add_spec_to_instance.rb +19 -0
- data/db/migrations/director/20151109190602_rename_orphan_columns.rb +13 -0
- data/lib/bosh/director.rb +19 -9
- data/lib/bosh/director/agent_client.rb +0 -17
- data/lib/bosh/director/api/cloud_config_manager.rb +7 -5
- data/lib/bosh/director/api/controllers/base_controller.rb +3 -2
- data/lib/bosh/director/api/controllers/cleanup_controller.rb +15 -0
- data/lib/bosh/director/api/controllers/deployments_controller.rb +38 -26
- data/lib/bosh/director/api/controllers/disks_controller.rb +20 -0
- data/lib/bosh/director/api/controllers/info_controller.rb +2 -2
- data/lib/bosh/director/api/controllers/releases_controller.rb +1 -16
- data/lib/bosh/director/api/controllers/stemcells_controller.rb +1 -9
- data/lib/bosh/director/api/deployment_manager.rb +2 -1
- data/lib/bosh/director/api/instance_lookup.rb +17 -0
- data/lib/bosh/director/api/instance_manager.rb +20 -10
- data/lib/bosh/director/api/release_manager.rb +28 -8
- data/lib/bosh/director/api/resurrector_manager.rb +9 -2
- data/lib/bosh/director/api/route_configuration.rb +2 -0
- data/lib/bosh/director/api/snapshot_manager.rb +9 -5
- data/lib/bosh/director/api/stemcell_manager.rb +50 -0
- data/lib/bosh/director/app.rb +1 -1
- data/lib/bosh/director/cloudcheck_helper.rb +119 -132
- data/lib/bosh/director/compile_task.rb +1 -1
- data/lib/bosh/director/compile_task_generator.rb +2 -2
- data/lib/bosh/director/config.rb +21 -12
- data/lib/bosh/director/deployment_deleter.rb +69 -0
- data/lib/bosh/director/deployment_plan.rb +35 -4
- data/lib/bosh/director/deployment_plan/agent_state_migrator.rb +47 -0
- data/lib/bosh/director/deployment_plan/assembler.rb +115 -241
- data/lib/bosh/director/deployment_plan/availability_zone.rb +27 -0
- data/lib/bosh/director/deployment_plan/cloud_manifest_parser.rb +144 -35
- data/lib/bosh/director/deployment_plan/compilation_config.rb +21 -19
- data/lib/bosh/director/deployment_plan/compilation_instance_pool.rb +169 -0
- data/lib/bosh/director/deployment_plan/deployment_repo.rb +4 -8
- data/lib/bosh/director/deployment_plan/deployment_spec_parser.rb +13 -1
- data/lib/bosh/director/deployment_plan/deployment_validator.rb +17 -0
- data/lib/bosh/director/deployment_plan/desired_instance.rb +15 -0
- data/lib/bosh/director/deployment_plan/{disk_pool.rb → disk_type.rb} +14 -19
- data/lib/bosh/director/deployment_plan/dynamic_network.rb +105 -53
- data/lib/bosh/director/deployment_plan/dynamic_network_subnet.rb +13 -0
- data/lib/bosh/director/deployment_plan/env.rb +18 -0
- data/lib/bosh/director/deployment_plan/global_network_resolver.rb +77 -0
- data/lib/bosh/director/deployment_plan/instance.rb +222 -390
- data/lib/bosh/director/deployment_plan/instance_network_reservations.rb +71 -0
- data/lib/bosh/director/deployment_plan/instance_plan.rb +336 -0
- data/lib/bosh/director/deployment_plan/instance_plan_factory.rb +54 -0
- data/lib/bosh/director/deployment_plan/instance_plan_sorter.rb +61 -0
- data/lib/bosh/director/deployment_plan/instance_planner.rb +101 -0
- data/lib/bosh/director/deployment_plan/instance_repository.rb +36 -0
- data/lib/bosh/director/deployment_plan/instance_spec.rb +154 -0
- data/lib/bosh/director/deployment_plan/ip_provider/database_ip_repo.rb +136 -0
- data/lib/bosh/director/deployment_plan/ip_provider/in_memory_ip_repo.rb +81 -0
- data/lib/bosh/director/deployment_plan/ip_provider/ip_provider.rb +153 -0
- data/lib/bosh/director/deployment_plan/ip_provider/ip_provider_factory.rb +22 -0
- data/lib/bosh/director/deployment_plan/job.rb +116 -53
- data/lib/bosh/director/deployment_plan/job_availability_zone_parser.rb +49 -0
- data/lib/bosh/director/deployment_plan/job_migrator.rb +90 -0
- data/lib/bosh/director/deployment_plan/job_network.rb +42 -0
- data/lib/bosh/director/deployment_plan/job_network_parser.rb +118 -0
- data/lib/bosh/director/deployment_plan/job_spec_parser.rb +123 -126
- data/lib/bosh/director/deployment_plan/links/link.rb +30 -0
- data/lib/bosh/director/deployment_plan/links/link_lookup.rb +66 -0
- data/lib/bosh/director/deployment_plan/links/link_path.rb +27 -0
- data/lib/bosh/director/deployment_plan/links/links_resolver.rb +70 -0
- data/lib/bosh/director/deployment_plan/links/template_link.rb +21 -0
- data/lib/bosh/director/deployment_plan/manifest_migrator.rb +3 -17
- data/lib/bosh/director/deployment_plan/manifest_validator.rb +46 -0
- data/lib/bosh/director/deployment_plan/manual_network.rb +70 -97
- data/lib/bosh/director/deployment_plan/manual_network_subnet.rb +148 -0
- data/lib/bosh/director/deployment_plan/network.rb +50 -39
- data/lib/bosh/director/deployment_plan/network_planner.rb +4 -0
- data/lib/bosh/director/deployment_plan/network_planner/plan.rb +26 -0
- data/lib/bosh/director/deployment_plan/network_planner/planner.rb +21 -0
- data/lib/bosh/director/deployment_plan/network_planner/reservation_reconciler.rb +81 -0
- data/lib/bosh/director/deployment_plan/network_planner/vip_static_ips_planner.rb +50 -0
- data/lib/bosh/director/deployment_plan/network_settings.rb +65 -0
- data/lib/bosh/director/deployment_plan/options/skip_drain.rb +7 -0
- data/lib/bosh/director/deployment_plan/package_validator.rb +79 -0
- data/lib/bosh/director/deployment_plan/placement_planner.rb +8 -0
- data/lib/bosh/director/deployment_plan/placement_planner/availability_zone_picker.rb +90 -0
- data/lib/bosh/director/deployment_plan/placement_planner/bruteforce_ip_allocation.rb +124 -0
- data/lib/bosh/director/deployment_plan/placement_planner/index_assigner.rb +32 -0
- data/lib/bosh/director/deployment_plan/placement_planner/networks_to_static_ips.rb +125 -0
- data/lib/bosh/director/deployment_plan/placement_planner/placed_desired_instances.rb +40 -0
- data/lib/bosh/director/deployment_plan/placement_planner/plan.rb +42 -0
- data/lib/bosh/director/deployment_plan/placement_planner/static_ips_availability_zone_picker.rb +237 -0
- data/lib/bosh/director/deployment_plan/placement_planner/unplaced_existing_instances.rb +53 -0
- data/lib/bosh/director/deployment_plan/planner.rb +186 -74
- data/lib/bosh/director/deployment_plan/planner_factory.rb +30 -147
- data/lib/bosh/director/deployment_plan/release_version.rb +3 -3
- data/lib/bosh/director/deployment_plan/resource_pool.rb +2 -174
- data/lib/bosh/director/deployment_plan/stemcell.rb +57 -14
- data/lib/bosh/director/deployment_plan/steps/package_compile_step.rb +28 -135
- data/lib/bosh/director/deployment_plan/steps/update_step.rb +23 -44
- data/lib/bosh/director/deployment_plan/template.rb +15 -4
- data/lib/bosh/director/deployment_plan/vip_network.rb +14 -42
- data/lib/bosh/director/deployment_plan/vm.rb +1 -99
- data/lib/bosh/director/deployment_plan/vm_type.rb +27 -0
- data/lib/bosh/director/disk_manager.rb +268 -0
- data/lib/bosh/director/dns/canonicalizer.rb +28 -0
- data/lib/bosh/director/dns/dns_manager.rb +163 -0
- data/lib/bosh/director/dns/local_dns_repo.rb +20 -0
- data/lib/bosh/director/dns/powerdns.rb +170 -0
- data/lib/bosh/director/errand/job_manager.rb +18 -29
- data/lib/bosh/director/error_ignorer.rb +16 -0
- data/lib/bosh/director/errors.rb +51 -20
- data/lib/bosh/director/event_log.rb +6 -0
- data/lib/bosh/director/instance_deleter.rb +53 -81
- data/lib/bosh/director/instance_reuser.rb +89 -0
- data/lib/bosh/director/instance_updater.rb +139 -281
- data/lib/bosh/director/instance_updater/preparer.rb +8 -5
- data/lib/bosh/director/instance_updater/state_applier.rb +21 -0
- data/lib/bosh/director/ip_util.rb +46 -26
- data/lib/bosh/director/job_renderer.rb +22 -10
- data/lib/bosh/director/job_runner.rb +1 -4
- data/lib/bosh/director/job_updater.rb +47 -35
- data/lib/bosh/director/job_updater_factory.rb +5 -4
- data/lib/bosh/director/jobs/base_job.rb +8 -0
- data/lib/bosh/director/jobs/cleanup_artifacts.rb +93 -0
- data/lib/bosh/director/jobs/delete_deployment.rb +10 -154
- data/lib/bosh/director/jobs/delete_deployment_snapshots.rb +1 -1
- data/lib/bosh/director/jobs/delete_orphan_disks.rb +44 -0
- data/lib/bosh/director/jobs/delete_release.rb +19 -196
- data/lib/bosh/director/jobs/delete_stemcell.rb +10 -76
- data/lib/bosh/director/jobs/export_release.rb +41 -121
- data/lib/bosh/director/jobs/fetch_logs.rb +0 -6
- data/lib/bosh/director/jobs/helpers.rb +10 -0
- data/lib/bosh/director/jobs/helpers/blob_deleter.rb +24 -0
- data/lib/bosh/director/jobs/helpers/compiled_package_deleter.rb +24 -0
- data/lib/bosh/director/jobs/helpers/name_version_release_deleter.rb +48 -0
- data/lib/bosh/director/jobs/helpers/package_deleter.rb +33 -0
- data/lib/bosh/director/jobs/helpers/release_deleter.rb +52 -0
- data/lib/bosh/director/jobs/helpers/release_version_deleter.rb +115 -0
- data/lib/bosh/director/jobs/helpers/releases_to_delete_picker.rb +31 -0
- data/lib/bosh/director/jobs/helpers/stemcell_deleter.rb +61 -0
- data/lib/bosh/director/jobs/helpers/stemcells_to_delete_picker.rb +30 -0
- data/lib/bosh/director/jobs/helpers/template_deleter.rb +20 -0
- data/lib/bosh/director/jobs/release/release_job.rb +18 -7
- data/lib/bosh/director/jobs/run_errand.rb +57 -36
- data/lib/bosh/director/jobs/scheduled_orphan_cleanup.rb +46 -0
- data/lib/bosh/director/jobs/ssh.rb +50 -17
- data/lib/bosh/director/jobs/update_deployment.rb +29 -11
- data/lib/bosh/director/jobs/update_release.rb +25 -4
- data/lib/bosh/director/jobs/vm_state.rb +23 -32
- data/lib/bosh/director/lock.rb +13 -8
- data/lib/bosh/director/logs_fetcher.rb +1 -1
- data/lib/bosh/director/models.rb +3 -0
- data/lib/bosh/director/models/compiled_package.rb +3 -3
- data/lib/bosh/director/models/deployment.rb +10 -0
- data/lib/bosh/director/models/instance.rb +77 -1
- data/lib/bosh/director/models/ip_address.rb +26 -0
- data/lib/bosh/director/models/orphan_disk.rb +23 -0
- data/lib/bosh/director/models/orphan_snapshot.rb +14 -0
- data/lib/bosh/director/models/template.rb +32 -9
- data/lib/bosh/director/models/vm.rb +5 -8
- data/lib/bosh/director/network_reservation.rb +69 -99
- data/lib/bosh/director/problem_handlers/inactive_disk.rb +5 -20
- data/lib/bosh/director/problem_handlers/missing_disk.rb +2 -13
- data/lib/bosh/director/problem_resolver.rb +2 -2
- data/lib/bosh/director/problem_scanner/vm_scan_stage.rb +2 -21
- data/lib/bosh/director/scheduler.rb +23 -6
- data/lib/bosh/director/{instance_updater/stopper.rb → stopper.rb} +24 -18
- data/lib/bosh/director/tagged_logger.rb +30 -0
- data/lib/bosh/director/transactor.rb +9 -0
- data/lib/bosh/director/version.rb +1 -1
- data/lib/bosh/director/vm_creator.rb +91 -19
- data/lib/bosh/director/vm_deleter.rb +25 -0
- data/lib/bosh/director/vm_recreator.rb +15 -0
- data/lib/cloud/dummy.rb +381 -94
- metadata +110 -30
- data/lib/bosh/director/deployment_plan/dns_binder.rb +0 -45
- data/lib/bosh/director/deployment_plan/instance_vm_binder.rb +0 -37
- data/lib/bosh/director/deployment_plan/network_subnet.rb +0 -166
- data/lib/bosh/director/deployment_plan/resource_pools.rb +0 -68
- data/lib/bosh/director/dns_helper.rb +0 -223
- data/lib/bosh/director/instance_updater/network_updater.rb +0 -110
- data/lib/bosh/director/instance_updater/vm_updater.rb +0 -189
- data/lib/bosh/director/problem_handlers/out_of_sync_vm.rb +0 -64
- data/lib/bosh/director/problem_handlers/unbound_instance_vm.rb +0 -85
- data/lib/bosh/director/resource_pool_updater.rb +0 -174
- data/lib/bosh/director/vm_data.rb +0 -63
- data/lib/bosh/director/vm_reuser.rb +0 -63
@@ -8,112 +8,14 @@ module Bosh::Director
|
|
8
8
|
# (network & storage) required for the VM to match the instance
|
9
9
|
# requirements.
|
10
10
|
class Vm
|
11
|
-
# @return [DeploymentPlan::ResourcePool] Associated resource pool
|
12
|
-
attr_reader :resource_pool
|
13
|
-
|
14
|
-
# @return [NetworkReservation] VM network reservation
|
15
|
-
attr_accessor :network_reservation
|
16
|
-
|
17
11
|
# @return [Models::Vm] Associated DB model
|
18
12
|
attr_accessor :model
|
19
13
|
|
20
|
-
# @return [Hash] Current state as provided by the BOSH Agent
|
21
|
-
attr_writer :current_state
|
22
|
-
|
23
14
|
# @return [DeploymentPlan::Instance, nil] Instance that reserved this VM
|
24
15
|
attr_accessor :bound_instance
|
25
16
|
|
26
|
-
def
|
27
|
-
if @current_state
|
28
|
-
@current_state.delete('release')
|
29
|
-
end
|
30
|
-
@current_state
|
31
|
-
end
|
32
|
-
|
33
|
-
##
|
34
|
-
# Creates a new idle VM reference for the specific resource pool
|
35
|
-
# @param [DeploymentPlan::ResourcePool] resource_pool Resource pool
|
36
|
-
def initialize(resource_pool)
|
37
|
-
@resource_pool = resource_pool
|
38
|
-
@current_state = nil
|
39
|
-
@bound_instance = nil
|
40
|
-
@network_reservation = nil
|
41
|
-
@model = nil
|
42
|
-
end
|
43
|
-
|
44
|
-
#
|
45
|
-
# @return [Boolean] Does this VM have a network reservation?
|
46
|
-
def has_network_reservation?
|
47
|
-
!@network_reservation.nil?
|
48
|
-
end
|
49
|
-
|
50
|
-
#
|
51
|
-
# Uses provided network reservation
|
52
|
-
# @param [NetworkReservation] reservation Network reservation
|
53
|
-
def use_reservation(reservation)
|
54
|
-
@network_reservation = reservation
|
55
|
-
end
|
56
|
-
|
57
|
-
#
|
58
|
-
# Releases current network reservation (if any)
|
59
|
-
# @return [void]
|
60
|
-
def release_reservation
|
61
|
-
if has_network_reservation?
|
62
|
-
@resource_pool.network.release(@network_reservation)
|
63
|
-
@network_reservation = nil
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
##
|
68
|
-
# @return [Hash] BOSH network settings used for Agent apply call
|
69
|
-
def network_settings
|
70
|
-
# use the instance network settings if bound, otherwise use the one
|
71
|
-
# provided by the resource pool
|
72
|
-
if @bound_instance
|
73
|
-
@bound_instance.network_settings
|
74
|
-
else
|
75
|
-
unless @network_reservation
|
76
|
-
raise NetworkReservationMissing,
|
77
|
-
'Missing network reservation for resource pool VM'
|
78
|
-
end
|
79
|
-
|
80
|
-
network_settings = {}
|
81
|
-
network = @resource_pool.network
|
82
|
-
network_settings[network.name] = network.network_settings(
|
83
|
-
@network_reservation)
|
84
|
-
network_settings
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
##
|
89
|
-
# @return [Boolean] returns true if the expected network configuration
|
90
|
-
# differs from the one provided by the VM
|
91
|
-
def networks_changed?
|
92
|
-
network_settings != @current_state['networks']
|
93
|
-
end
|
94
|
-
|
95
|
-
##
|
96
|
-
# @return [Boolean] returns true if the expected resource pool
|
97
|
-
# specification differs from the one provided by the VM
|
98
|
-
def resource_pool_changed?
|
99
|
-
return true if resource_pool.spec != @current_state['resource_pool']
|
100
|
-
return true if resource_pool.deployment_plan.recreate
|
101
|
-
return true if @model && @model.env != resource_pool.env
|
102
|
-
|
103
|
-
false
|
104
|
-
end
|
105
|
-
|
106
|
-
##
|
107
|
-
# @return [Boolean] returns true if the any of the expected specifications
|
108
|
-
# differ from the ones provided by the VM
|
109
|
-
def changed?
|
110
|
-
resource_pool_changed? || networks_changed?
|
111
|
-
end
|
112
|
-
|
113
|
-
#TODO: rename 'clean'
|
114
|
-
def clean_vm
|
17
|
+
def clean
|
115
18
|
self.model = nil
|
116
|
-
self.current_state = nil
|
117
19
|
end
|
118
20
|
end
|
119
21
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Bosh::Director
|
2
|
+
module DeploymentPlan
|
3
|
+
class VmType
|
4
|
+
include ValidationHelper
|
5
|
+
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
attr_reader :cloud_properties
|
9
|
+
|
10
|
+
def initialize(spec)
|
11
|
+
|
12
|
+
@name = safe_property(spec, "name", class: String)
|
13
|
+
|
14
|
+
@cloud_properties =
|
15
|
+
safe_property(spec, "cloud_properties", class: Hash, default: {})
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def spec
|
20
|
+
{
|
21
|
+
"name" => @name,
|
22
|
+
"cloud_properties" => @cloud_properties,
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,268 @@
|
|
1
|
+
module Bosh::Director
|
2
|
+
class DiskManager
|
3
|
+
|
4
|
+
def initialize(cloud, logger)
|
5
|
+
@cloud = cloud
|
6
|
+
@logger = logger
|
7
|
+
@transactor = Transactor.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def update_persistent_disk(instance_plan, vm_recreator)
|
11
|
+
@logger.info('Updating persistent disk')
|
12
|
+
check_persistent_disk(instance_plan)
|
13
|
+
|
14
|
+
return unless instance_plan.persistent_disk_changed?
|
15
|
+
|
16
|
+
instance = instance_plan.instance
|
17
|
+
old_disk = instance.model.persistent_disk
|
18
|
+
|
19
|
+
disk = nil
|
20
|
+
if instance_plan.needs_disk?
|
21
|
+
disk = create_and_attach_disk(instance_plan, vm_recreator)
|
22
|
+
mount_and_migrate_disk(instance, disk, old_disk)
|
23
|
+
end
|
24
|
+
|
25
|
+
@transactor.retryable_transaction(Bosh::Director::Config.db) do
|
26
|
+
old_disk.update(:active => false) if old_disk
|
27
|
+
disk.update(:active => true) if disk
|
28
|
+
end
|
29
|
+
|
30
|
+
delete_mounted_persistent_disk(instance, old_disk) if old_disk
|
31
|
+
end
|
32
|
+
|
33
|
+
def attach_disks_if_needed(instance_plan)
|
34
|
+
unless instance_plan.needs_disk?
|
35
|
+
@logger.warn('Skipping disk attachment, instance no longer needs disk')
|
36
|
+
return
|
37
|
+
end
|
38
|
+
|
39
|
+
instance = instance_plan.instance
|
40
|
+
disk_cid = instance.model.persistent_disk_cid
|
41
|
+
return @logger.info('Skipping disk attaching') if disk_cid.nil?
|
42
|
+
vm_model = instance.vm.model
|
43
|
+
begin
|
44
|
+
@cloud.attach_disk(vm_model.cid, disk_cid)
|
45
|
+
AgentClient.with_vm(vm_model).mount_disk(disk_cid)
|
46
|
+
rescue => e
|
47
|
+
@logger.warn("Failed to attach disk to new VM: #{e.inspect}")
|
48
|
+
raise e
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def delete_persistent_disks(instance_model)
|
53
|
+
instance_model.persistent_disks.each do |disk|
|
54
|
+
orphan_disk(disk)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def orphan_disk(disk)
|
59
|
+
@transactor.retryable_transaction(Bosh::Director::Config.db) do
|
60
|
+
orphan_disk = Models::OrphanDisk.create(
|
61
|
+
disk_cid: disk.disk_cid,
|
62
|
+
size: disk.size,
|
63
|
+
availability_zone: disk.instance.availability_zone,
|
64
|
+
deployment_name: disk.instance.deployment.name,
|
65
|
+
instance_name: "#{disk.instance.job}/#{disk.instance.uuid}",
|
66
|
+
cloud_properties: disk.cloud_properties
|
67
|
+
)
|
68
|
+
|
69
|
+
orphan_snapshots(disk.snapshots, orphan_disk)
|
70
|
+
@logger.info("Orphaning disk: '#{disk.disk_cid}', " +
|
71
|
+
"#{disk.active ? "active" : "inactive"}")
|
72
|
+
|
73
|
+
disk.destroy
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def list_orphan_disks
|
78
|
+
Models::OrphanDisk.all.map do |disk|
|
79
|
+
{
|
80
|
+
'disk_cid' => disk.disk_cid,
|
81
|
+
'size' => disk.size,
|
82
|
+
'az' => disk.availability_zone,
|
83
|
+
'deployment_name' => disk.deployment_name,
|
84
|
+
'instance_name' => disk.instance_name,
|
85
|
+
'cloud_properties' => disk.cloud_properties,
|
86
|
+
'orphaned_at' => disk.created_at.to_s
|
87
|
+
}
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def delete_orphan_disk_by_disk_cid(disk_cid)
|
92
|
+
@logger.info("Deleting orphan disk: #{disk_cid}")
|
93
|
+
orphan_disk = Bosh::Director::Models::OrphanDisk.where(disk_cid: disk_cid).first
|
94
|
+
if orphan_disk
|
95
|
+
delete_orphan_disk(orphan_disk)
|
96
|
+
else
|
97
|
+
@logger.debug("Disk not found: #{disk_cid}")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def unmount_disk_for(instance_plan)
|
102
|
+
disk = instance_plan.instance.model.persistent_disk
|
103
|
+
return if disk.nil?
|
104
|
+
unmount(instance_plan.instance, disk)
|
105
|
+
end
|
106
|
+
|
107
|
+
def delete_orphan_disk(orphan_disk)
|
108
|
+
begin
|
109
|
+
orphan_disk.orphan_snapshots.each do |orphan_snapshot|
|
110
|
+
delete_orphan_snapshot(orphan_snapshot)
|
111
|
+
end
|
112
|
+
@logger.info("Deleting orphan orphan disk: #{orphan_disk.disk_cid}")
|
113
|
+
@cloud.delete_disk(orphan_disk.disk_cid)
|
114
|
+
orphan_disk.destroy
|
115
|
+
rescue Bosh::Clouds::DiskNotFound
|
116
|
+
@logger.debug("Disk not found in IaaS: #{orphan_disk.disk_cid}")
|
117
|
+
orphan_disk.destroy
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def delete_orphan_snapshot(orphan_snapshot)
|
124
|
+
begin
|
125
|
+
snapshot_cid = orphan_snapshot.snapshot_cid
|
126
|
+
@logger.info("Deleting orphan snapshot: #{snapshot_cid}")
|
127
|
+
@cloud.delete_snapshot(snapshot_cid)
|
128
|
+
orphan_snapshot.destroy
|
129
|
+
rescue Bosh::Clouds::DiskNotFound
|
130
|
+
@logger.debug("Disk not found in IaaS: #{snapshot_cid}")
|
131
|
+
orphan_snapshot.destroy
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def orphan_snapshots(snapshots, orphan_disk)
|
136
|
+
snapshots.each do |snapshot|
|
137
|
+
@logger.info("Orphaning snapshot: '#{snapshot.snapshot_cid}'")
|
138
|
+
Models::OrphanSnapshot.create(
|
139
|
+
orphan_disk: orphan_disk,
|
140
|
+
snapshot_cid: snapshot.snapshot_cid,
|
141
|
+
clean: snapshot.clean,
|
142
|
+
snapshot_created_at: snapshot.created_at
|
143
|
+
)
|
144
|
+
snapshot.delete
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def delete_mounted_persistent_disk(instance, disk)
|
149
|
+
unmount(instance, disk)
|
150
|
+
|
151
|
+
disk_cid = disk.disk_cid
|
152
|
+
if disk_cid.nil?
|
153
|
+
@logger.info('Skipping disk detaching, instance does not have a disk')
|
154
|
+
return
|
155
|
+
end
|
156
|
+
|
157
|
+
begin
|
158
|
+
@logger.info("Detaching disk #{disk_cid}")
|
159
|
+
@cloud.detach_disk(instance.model.vm.cid, disk_cid)
|
160
|
+
rescue Bosh::Clouds::DiskNotAttached
|
161
|
+
if disk.active
|
162
|
+
raise CloudDiskNotAttached,
|
163
|
+
"`#{instance}' VM should have persistent disk attached " +
|
164
|
+
"but it doesn't (according to CPI)"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
orphan_disk(disk)
|
169
|
+
end
|
170
|
+
|
171
|
+
def unmount(instance, disk)
|
172
|
+
disk_cid = disk.disk_cid
|
173
|
+
if disk_cid.nil?
|
174
|
+
@logger.info('Skipping disk unmounting, instance does not have a disk')
|
175
|
+
return
|
176
|
+
end
|
177
|
+
|
178
|
+
if disks(instance).include?(disk_cid)
|
179
|
+
@logger.info("Stopping instance '#{instance}' before unmount")
|
180
|
+
agent(instance).stop
|
181
|
+
@logger.info("Unmounting disk '#{disk_cid}'")
|
182
|
+
agent(instance).unmount_disk(disk_cid)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# Synchronizes persistent_disks with the agent.
|
187
|
+
# (Currently assumes that we only have 1 persistent disk.)
|
188
|
+
# @return [void]
|
189
|
+
def check_persistent_disk(instance_plan)
|
190
|
+
instance = instance_plan.instance
|
191
|
+
return if instance.model.persistent_disks.empty?
|
192
|
+
agent_disk_cid = disks(instance).first
|
193
|
+
|
194
|
+
if agent_disk_cid.nil? && !instance_plan.needs_disk?
|
195
|
+
@logger.debug('Disk is already detached')
|
196
|
+
elsif agent_disk_cid != instance.model.persistent_disk_cid
|
197
|
+
raise AgentDiskOutOfSync,
|
198
|
+
"`#{instance}' has invalid disks: agent reports " +
|
199
|
+
"`#{agent_disk_cid}' while director record shows " +
|
200
|
+
"`#{instance.model.persistent_disk_cid}'"
|
201
|
+
end
|
202
|
+
|
203
|
+
instance.model.persistent_disks.each do |disk|
|
204
|
+
unless disk.active
|
205
|
+
@logger.warn("`#{instance}' has inactive disk #{disk.disk_cid}")
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def disks(instance)
|
211
|
+
agent(instance).list_disk
|
212
|
+
end
|
213
|
+
|
214
|
+
def agent(instance)
|
215
|
+
AgentClient.with_vm(instance.vm.model)
|
216
|
+
end
|
217
|
+
|
218
|
+
def create_and_attach_disk(instance_plan, vm_recreator)
|
219
|
+
instance = instance_plan.instance
|
220
|
+
disk = create_disk(instance_plan)
|
221
|
+
@cloud.attach_disk(instance.model.vm.cid, disk.disk_cid)
|
222
|
+
return disk
|
223
|
+
rescue Bosh::Clouds::NoDiskSpace => e
|
224
|
+
if e.ok_to_retry
|
225
|
+
@logger.warn('Retrying attach disk operation after persistent disk update failed')
|
226
|
+
# Re-creating the vm may cause it to be re-created in a place with more storage
|
227
|
+
unmount_disk_for(instance_plan)
|
228
|
+
vm_recreator.recreate_vm(instance_plan, disk.disk_cid)
|
229
|
+
begin
|
230
|
+
@cloud.attach_disk(instance.model.vm.cid, disk.disk_cid)
|
231
|
+
rescue
|
232
|
+
orphan_disk(disk)
|
233
|
+
raise
|
234
|
+
end
|
235
|
+
else
|
236
|
+
orphan_disk(disk)
|
237
|
+
raise
|
238
|
+
end
|
239
|
+
return disk
|
240
|
+
end
|
241
|
+
|
242
|
+
def mount_and_migrate_disk(instance, new_disk, old_disk)
|
243
|
+
agent(instance).mount_disk(new_disk.disk_cid)
|
244
|
+
agent(instance).migrate_disk(old_disk.disk_cid, new_disk.disk_cid) if old_disk
|
245
|
+
rescue => e
|
246
|
+
@logger.debug("Failed to migrate disk, deleting new disk. #{e.inspect}")
|
247
|
+
delete_mounted_persistent_disk(instance, new_disk)
|
248
|
+
raise e
|
249
|
+
end
|
250
|
+
|
251
|
+
def create_disk(instance_plan)
|
252
|
+
job = instance_plan.desired_instance.job
|
253
|
+
instance_model = instance_plan.instance.model
|
254
|
+
|
255
|
+
disk_size = job.persistent_disk_type.disk_size
|
256
|
+
cloud_properties = job.persistent_disk_type.cloud_properties
|
257
|
+
|
258
|
+
disk_cid = @cloud.create_disk(disk_size, cloud_properties, instance_model.vm.cid)
|
259
|
+
Models::PersistentDisk.create(
|
260
|
+
disk_cid: disk_cid,
|
261
|
+
active: false,
|
262
|
+
instance_id: instance_model.id,
|
263
|
+
size: disk_size,
|
264
|
+
cloud_properties: cloud_properties,
|
265
|
+
)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Bosh::Director
|
2
|
+
class Canonicalizer
|
3
|
+
|
4
|
+
def self.canonicalize(string, opts = {})
|
5
|
+
# a-z, 0-9, -, case insensitive, and must start with a letter
|
6
|
+
string = string.downcase.gsub(/_/, "-")
|
7
|
+
if opts[:allow_dots]
|
8
|
+
string = string.gsub(/[^a-z0-9\-\.]/, "")
|
9
|
+
else
|
10
|
+
string = string.gsub(/[^a-z0-9\-]/, "")
|
11
|
+
end
|
12
|
+
|
13
|
+
validate_dns_name(string)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.validate_dns_name(string)
|
17
|
+
if string =~ /^(\d|-)/
|
18
|
+
raise DnsInvalidCanonicalName,
|
19
|
+
"Invalid DNS canonical name `#{string}', must begin with a letter"
|
20
|
+
end
|
21
|
+
if string =~ /-$/
|
22
|
+
raise DnsInvalidCanonicalName,
|
23
|
+
"Invalid DNS canonical name `#{string}', can't end with a hyphen"
|
24
|
+
end
|
25
|
+
string
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Bosh::Director
|
2
|
+
class DnsManager
|
3
|
+
attr_reader :dns_domain_name
|
4
|
+
|
5
|
+
def self.create
|
6
|
+
dns_config = Config.dns || {}
|
7
|
+
dns_enabled = !!Config.dns_db # to be consistent with current behavior
|
8
|
+
logger = Config.logger
|
9
|
+
local_dns_repo = LocalDnsRepo.new(logger)
|
10
|
+
dns_domain_name = Canonicalizer.canonicalize(dns_config.fetch('domain_name', 'bosh'), :allow_dots => true)
|
11
|
+
dns_provider = PowerDns.new(dns_domain_name, logger)
|
12
|
+
|
13
|
+
new(dns_domain_name, dns_config, dns_enabled, dns_provider, local_dns_repo, logger)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(dns_domain_name, dns_config, dns_enabled, dns_provider, local_dns_repo, logger)
|
17
|
+
@dns_domain_name = dns_domain_name
|
18
|
+
@dns_provider = dns_provider
|
19
|
+
@dns_enabled = dns_enabled
|
20
|
+
@default_server = dns_config['server']
|
21
|
+
@flush_command = dns_config['flush_command']
|
22
|
+
@ip_address = dns_config['address']
|
23
|
+
@local_dns_repo = local_dns_repo
|
24
|
+
@logger = logger
|
25
|
+
end
|
26
|
+
|
27
|
+
def dns_enabled?
|
28
|
+
@dns_enabled
|
29
|
+
end
|
30
|
+
|
31
|
+
def configure_nameserver
|
32
|
+
return unless dns_enabled?
|
33
|
+
|
34
|
+
@dns_provider.create_or_update_nameserver(@ip_address)
|
35
|
+
end
|
36
|
+
|
37
|
+
def find_dns_record(dns_record_name, ip_address)
|
38
|
+
@dns_provider.find_dns_record(dns_record_name, ip_address)
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_dns_record_names_by_instance(instance_model)
|
42
|
+
instance_model.nil? ? [] : instance_model.dns_record_names.to_a.compact
|
43
|
+
end
|
44
|
+
|
45
|
+
def update_dns_record_for_instance(instance_model, dns_names_to_ip)
|
46
|
+
current_dns_records = @local_dns_repo.find(instance_model)
|
47
|
+
new_dns_records = []
|
48
|
+
dns_names_to_ip.each do |record_name, ip_address|
|
49
|
+
new_dns_records << record_name
|
50
|
+
@logger.info("Updating DNS for: #{record_name} to #{ip_address}")
|
51
|
+
@dns_provider.create_or_update_dns_records(record_name, ip_address)
|
52
|
+
end
|
53
|
+
dns_records = (current_dns_records + new_dns_records).uniq
|
54
|
+
@local_dns_repo.create_or_update(instance_model, dns_records)
|
55
|
+
end
|
56
|
+
|
57
|
+
def migrate_legacy_records(instance_model)
|
58
|
+
return unless dns_enabled?
|
59
|
+
|
60
|
+
return if @local_dns_repo.find(instance_model).any?
|
61
|
+
|
62
|
+
index_pattern_for_all_networks = dns_record_name(
|
63
|
+
instance_model.index,
|
64
|
+
instance_model.job,
|
65
|
+
'%',
|
66
|
+
instance_model.deployment.name
|
67
|
+
)
|
68
|
+
uuid_pattern_for_all_networks = dns_record_name(
|
69
|
+
instance_model.uuid,
|
70
|
+
instance_model.job,
|
71
|
+
'%',
|
72
|
+
instance_model.deployment.name
|
73
|
+
)
|
74
|
+
|
75
|
+
legacy_record_names = [index_pattern_for_all_networks, uuid_pattern_for_all_networks]
|
76
|
+
.map { |pattern| @dns_provider.find_dns_records_by_pattern(pattern) }
|
77
|
+
.flatten
|
78
|
+
.map(&:name)
|
79
|
+
|
80
|
+
@local_dns_repo.create_or_update(instance_model, legacy_record_names)
|
81
|
+
end
|
82
|
+
|
83
|
+
def delete_dns_for_instance(instance_model)
|
84
|
+
return unless dns_enabled?
|
85
|
+
|
86
|
+
current_dns_records = @local_dns_repo.find(instance_model)
|
87
|
+
if current_dns_records.empty?
|
88
|
+
# for backwards compatibility when old instances
|
89
|
+
# did not have records in local repo
|
90
|
+
# we cannot migrate them because powerdns can be different database
|
91
|
+
# those instance only had index-based dns records (before global-net)
|
92
|
+
index_record_pattern = dns_record_name(instance_model.index, instance_model.job, '%', instance_model.deployment.name)
|
93
|
+
@dns_provider.delete(index_record_pattern)
|
94
|
+
return
|
95
|
+
end
|
96
|
+
|
97
|
+
current_dns_records.each do |record_name|
|
98
|
+
@logger.info("Removing DNS for: #{record_name}")
|
99
|
+
@dns_provider.delete(record_name)
|
100
|
+
end
|
101
|
+
|
102
|
+
@local_dns_repo.delete(instance_model)
|
103
|
+
end
|
104
|
+
|
105
|
+
# build a list of dns servers to use
|
106
|
+
def dns_servers(network, dns_spec, add_default_dns = true)
|
107
|
+
servers = nil
|
108
|
+
|
109
|
+
if dns_spec
|
110
|
+
servers = []
|
111
|
+
dns_spec.each do |dns|
|
112
|
+
dns = NetAddr::CIDR.create(dns)
|
113
|
+
unless dns.size == 1
|
114
|
+
raise NetworkInvalidDns,
|
115
|
+
"Invalid DNS for network `#{network}': must be a single IP"
|
116
|
+
end
|
117
|
+
|
118
|
+
servers << dns.ip
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
return servers unless add_default_dns
|
123
|
+
add_default_dns_server(servers)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Purge cached DNS records
|
127
|
+
def flush_dns_cache
|
128
|
+
if @flush_command && !@flush_command.empty?
|
129
|
+
stdout, stderr, status = Open3.capture3(@flush_command)
|
130
|
+
if status == 0
|
131
|
+
@logger.debug("Flushed #{stdout.chomp} records from DNS cache")
|
132
|
+
else
|
133
|
+
@logger.warn("Failed to flush DNS cache: #{stderr.chomp}")
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def dns_record_name(hostname, job_name, network_name, deployment_name)
|
139
|
+
network_name = Canonicalizer.canonicalize(network_name) unless network_name == '%'
|
140
|
+
|
141
|
+
[ hostname,
|
142
|
+
Canonicalizer.canonicalize(job_name),
|
143
|
+
network_name,
|
144
|
+
Canonicalizer.canonicalize(deployment_name),
|
145
|
+
@dns_domain_name
|
146
|
+
].join('.')
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
# add default dns server to an array of dns servers
|
152
|
+
def add_default_dns_server(servers)
|
153
|
+
return servers unless dns_enabled?
|
154
|
+
|
155
|
+
unless @default_server.to_s.empty? || @default_server == '127.0.0.1'
|
156
|
+
(servers ||= []) << @default_server
|
157
|
+
servers.uniq!
|
158
|
+
end
|
159
|
+
|
160
|
+
servers
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|