bosh-director 1.2619.0 → 1.2624.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/bosh/director/deployment_plan.rb +1 -1
- data/lib/bosh/director/deployment_plan/assembler.rb +44 -51
- data/lib/bosh/director/deployment_plan/deployment_spec_parser.rb +1 -1
- data/lib/bosh/director/deployment_plan/instance.rb +112 -50
- data/lib/bosh/director/deployment_plan/instance_vm_binder.rb +5 -27
- data/lib/bosh/director/deployment_plan/job.rb +6 -7
- data/lib/bosh/director/deployment_plan/job_spec_parser.rb +3 -2
- data/lib/bosh/director/deployment_plan/resource_pool.rb +35 -31
- data/lib/bosh/director/deployment_plan/{idle_vm.rb → vm.rb} +7 -6
- data/lib/bosh/director/errand/job_manager.rb +1 -1
- data/lib/bosh/director/instance_updater/vm_updater.rb +2 -38
- data/lib/bosh/director/resource_pool_updater.rb +48 -52
- data/lib/bosh/director/version.rb +1 -1
- metadata +25 -25
|
@@ -4,7 +4,7 @@ module Bosh::Director
|
|
|
4
4
|
end
|
|
5
5
|
|
|
6
6
|
require 'bosh/director/deployment_plan/compilation_config'
|
|
7
|
-
require 'bosh/director/deployment_plan/
|
|
7
|
+
require 'bosh/director/deployment_plan/vm'
|
|
8
8
|
require 'bosh/director/deployment_plan/instance'
|
|
9
9
|
require 'bosh/director/deployment_plan/job'
|
|
10
10
|
require 'bosh/director/deployment_plan/network'
|
|
@@ -35,10 +35,10 @@ module Bosh::Director
|
|
|
35
35
|
def bind_existing_deployment
|
|
36
36
|
lock = Mutex.new
|
|
37
37
|
ThreadPool.new(:max_threads => Config.max_threads).wrap do |pool|
|
|
38
|
-
@deployment_plan.vms.each do |
|
|
38
|
+
@deployment_plan.vms.each do |vm_model|
|
|
39
39
|
pool.process do
|
|
40
|
-
with_thread_name("bind_existing_deployment(#{
|
|
41
|
-
bind_existing_vm(
|
|
40
|
+
with_thread_name("bind_existing_deployment(#{vm_model.agent_id})") do
|
|
41
|
+
bind_existing_vm(vm_model, lock)
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
end
|
|
@@ -46,15 +46,15 @@ module Bosh::Director
|
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
# Queries agent for VM state and updates deployment plan accordingly
|
|
49
|
-
# @param [Models::Vm]
|
|
49
|
+
# @param [Models::Vm] vm_model VM database model
|
|
50
50
|
# @param [Mutex] lock Lock to hold on to while updating deployment plan
|
|
51
|
-
def bind_existing_vm(
|
|
52
|
-
state = get_state(
|
|
51
|
+
def bind_existing_vm(vm_model, lock)
|
|
52
|
+
state = get_state(vm_model)
|
|
53
53
|
lock.synchronize do
|
|
54
54
|
@logger.debug('Processing VM network reservations')
|
|
55
55
|
reservations = get_network_reservations(state)
|
|
56
56
|
|
|
57
|
-
instance =
|
|
57
|
+
instance = vm_model.instance
|
|
58
58
|
if instance
|
|
59
59
|
bind_instance(instance, state, reservations)
|
|
60
60
|
else
|
|
@@ -62,10 +62,10 @@ module Bosh::Director
|
|
|
62
62
|
resource_pool = @deployment_plan.resource_pool(resource_pool_name)
|
|
63
63
|
if resource_pool
|
|
64
64
|
@logger.debug("Binding VM to resource pool '#{resource_pool_name}'")
|
|
65
|
-
bind_idle_vm(
|
|
65
|
+
bind_idle_vm(vm_model, resource_pool, state, reservations)
|
|
66
66
|
else
|
|
67
67
|
@logger.debug("Resource pool '#{resource_pool_name}' does not exist, marking VM for deletion")
|
|
68
|
-
@deployment_plan.delete_vm(
|
|
68
|
+
@deployment_plan.delete_vm(vm_model)
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
71
|
@logger.debug('Finished processing VM network reservations')
|
|
@@ -73,36 +73,36 @@ module Bosh::Director
|
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
# Binds idle VM to a resource pool with a proper network reservation
|
|
76
|
-
# @param [Models::Vm]
|
|
76
|
+
# @param [Models::Vm] vm_model VM DB model
|
|
77
77
|
# @param [DeploymentPlan::ResourcePool] resource_pool Resource pool
|
|
78
78
|
# @param [Hash] state VM state according to its agent
|
|
79
79
|
# @param [Hash] reservations Network reservations
|
|
80
|
-
def bind_idle_vm(
|
|
80
|
+
def bind_idle_vm(vm_model, resource_pool, state, reservations)
|
|
81
81
|
if reservations.any? { |network_name, reservation| reservation.static? }
|
|
82
|
-
@logger.debug("Releasing all network reservations for VM `#{
|
|
82
|
+
@logger.debug("Releasing all network reservations for VM `#{vm_model.cid}'")
|
|
83
83
|
reservations.each do |network_name, reservation|
|
|
84
|
-
@logger.debug("Releasing #{reservation.type} network reservation `#{network_name}' for VM `#{
|
|
84
|
+
@logger.debug("Releasing #{reservation.type} network reservation `#{network_name}' for VM `#{vm_model.cid}'")
|
|
85
85
|
resource_pool.network.release(reservation)
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
-
@logger.debug("Deleting VM `#{
|
|
89
|
-
@deployment_plan.delete_vm(
|
|
88
|
+
@logger.debug("Deleting VM `#{vm_model.cid}' with static network reservation")
|
|
89
|
+
@deployment_plan.delete_vm(vm_model)
|
|
90
90
|
return
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
-
@logger.debug("Adding VM `#{
|
|
93
|
+
@logger.debug("Adding VM `#{vm_model.cid}' to resource pool `#{resource_pool.name}'")
|
|
94
94
|
idle_vm = resource_pool.add_idle_vm
|
|
95
|
-
idle_vm.
|
|
95
|
+
idle_vm.model = vm_model
|
|
96
96
|
idle_vm.current_state = state
|
|
97
97
|
|
|
98
98
|
network_name = resource_pool.network.name
|
|
99
99
|
reservation = reservations[network_name]
|
|
100
100
|
if reservation
|
|
101
101
|
@logger.debug("Using existing `#{reservation.type}' " +
|
|
102
|
-
"network reservation of `#{reservation.ip}' for VM `#{
|
|
102
|
+
"network reservation of `#{reservation.ip}' for VM `#{vm_model.cid}'")
|
|
103
103
|
idle_vm.use_reservation(reservation)
|
|
104
104
|
else
|
|
105
|
-
@logger.debug("No network reservation for VM `#{
|
|
105
|
+
@logger.debug("No network reservation for VM `#{vm_model.cid}'")
|
|
106
106
|
end
|
|
107
107
|
end
|
|
108
108
|
|
|
@@ -139,15 +139,8 @@ module Bosh::Director
|
|
|
139
139
|
return
|
|
140
140
|
end
|
|
141
141
|
|
|
142
|
-
@logger.debug("Found job instance `#{instance_name}'")
|
|
143
|
-
instance.
|
|
144
|
-
instance.current_state = state
|
|
145
|
-
|
|
146
|
-
@logger.debug("Copying job instance `#{instance_name}' network reservations")
|
|
147
|
-
instance.take_network_reservations(reservations)
|
|
148
|
-
|
|
149
|
-
@logger.debug("Copying job instance `#{instance_name}' resource pool reservation")
|
|
150
|
-
job.resource_pool.mark_active_vm
|
|
142
|
+
@logger.debug("Found existing job instance `#{instance_name}'")
|
|
143
|
+
instance.bind_existing_instance(instance_model, state, reservations)
|
|
151
144
|
end
|
|
152
145
|
|
|
153
146
|
def get_network_reservations(state)
|
|
@@ -163,16 +156,16 @@ module Bosh::Director
|
|
|
163
156
|
reservations
|
|
164
157
|
end
|
|
165
158
|
|
|
166
|
-
def get_state(
|
|
167
|
-
@logger.debug("Requesting current VM state for: #{
|
|
168
|
-
agent = AgentClient.with_defaults(
|
|
159
|
+
def get_state(vm_model)
|
|
160
|
+
@logger.debug("Requesting current VM state for: #{vm_model.agent_id}")
|
|
161
|
+
agent = AgentClient.with_defaults(vm_model.agent_id)
|
|
169
162
|
state = agent.get_state
|
|
170
163
|
|
|
171
164
|
@logger.debug("Received VM state: #{state.pretty_inspect}")
|
|
172
|
-
verify_state(
|
|
165
|
+
verify_state(vm_model, state)
|
|
173
166
|
@logger.debug('Verified VM state')
|
|
174
167
|
|
|
175
|
-
migrate_legacy_state(
|
|
168
|
+
migrate_legacy_state(vm_model, state)
|
|
176
169
|
state.delete('release')
|
|
177
170
|
if state.include?('job')
|
|
178
171
|
state['job'].delete('release')
|
|
@@ -180,21 +173,21 @@ module Bosh::Director
|
|
|
180
173
|
state
|
|
181
174
|
end
|
|
182
175
|
|
|
183
|
-
def verify_state(
|
|
184
|
-
instance =
|
|
176
|
+
def verify_state(vm_model, state)
|
|
177
|
+
instance = vm_model.instance
|
|
185
178
|
|
|
186
|
-
if instance && instance.deployment_id !=
|
|
179
|
+
if instance && instance.deployment_id != vm_model.deployment_id
|
|
187
180
|
# Both VM and instance should reference same deployment
|
|
188
181
|
raise VmInstanceOutOfSync,
|
|
189
|
-
"VM `#{
|
|
182
|
+
"VM `#{vm_model.cid}' and instance " +
|
|
190
183
|
"`#{instance.job}/#{instance.index}' " +
|
|
191
184
|
"don't belong to the same deployment"
|
|
192
185
|
end
|
|
193
186
|
|
|
194
187
|
unless state.kind_of?(Hash)
|
|
195
|
-
@logger.error("Invalid state for `#{
|
|
188
|
+
@logger.error("Invalid state for `#{vm_model.cid}': #{state.pretty_inspect}")
|
|
196
189
|
raise AgentInvalidStateFormat,
|
|
197
|
-
"VM `#{
|
|
190
|
+
"VM `#{vm_model.cid}' returns invalid state: " +
|
|
198
191
|
"expected Hash, got #{state.class}"
|
|
199
192
|
end
|
|
200
193
|
|
|
@@ -203,7 +196,7 @@ module Bosh::Director
|
|
|
203
196
|
|
|
204
197
|
if actual_deployment_name != expected_deployment_name
|
|
205
198
|
raise AgentWrongDeployment,
|
|
206
|
-
"VM `#{
|
|
199
|
+
"VM `#{vm_model.cid}' is out of sync: " +
|
|
207
200
|
'expected to be a part of deployment ' +
|
|
208
201
|
"`#{expected_deployment_name}' " +
|
|
209
202
|
'but is actually a part of deployment ' +
|
|
@@ -215,7 +208,7 @@ module Bosh::Director
|
|
|
215
208
|
|
|
216
209
|
if instance.nil? && !actual_job.nil?
|
|
217
210
|
raise AgentUnexpectedJob,
|
|
218
|
-
"VM `#{
|
|
211
|
+
"VM `#{vm_model.cid}' is out of sync: " +
|
|
219
212
|
"it reports itself as `#{actual_job}/#{actual_index}' but " +
|
|
220
213
|
'there is no instance reference in DB'
|
|
221
214
|
end
|
|
@@ -237,22 +230,22 @@ module Bosh::Director
|
|
|
237
230
|
end
|
|
238
231
|
else
|
|
239
232
|
raise AgentJobMismatch,
|
|
240
|
-
"VM `#{
|
|
233
|
+
"VM `#{vm_model.cid}' is out of sync: " +
|
|
241
234
|
"it reports itself as `#{actual_job}/#{actual_index}' but " +
|
|
242
235
|
"according to DB it is `#{instance.job}/#{instance.index}'"
|
|
243
236
|
end
|
|
244
237
|
end
|
|
245
238
|
end
|
|
246
239
|
|
|
247
|
-
def migrate_legacy_state(
|
|
240
|
+
def migrate_legacy_state(vm_model, state)
|
|
248
241
|
# Persisting apply spec for VMs that were introduced before we started
|
|
249
242
|
# persisting it on apply itself (this is for cloudcheck purposes only)
|
|
250
|
-
if
|
|
243
|
+
if vm_model.apply_spec.nil?
|
|
251
244
|
# The assumption is that apply_spec <=> VM state
|
|
252
|
-
|
|
245
|
+
vm_model.update(:apply_spec => state)
|
|
253
246
|
end
|
|
254
247
|
|
|
255
|
-
instance =
|
|
248
|
+
instance = vm_model.instance
|
|
256
249
|
if instance
|
|
257
250
|
disk_size = state['persistent_disk'].to_i
|
|
258
251
|
persistent_disk = instance.persistent_disk
|
|
@@ -354,12 +347,12 @@ module Bosh::Director
|
|
|
354
347
|
|
|
355
348
|
@event_log.begin_stage('Deleting unneeded VMs', unneeded_vms.size)
|
|
356
349
|
ThreadPool.new(:max_threads => Config.max_threads).wrap do |pool|
|
|
357
|
-
unneeded_vms.each do |
|
|
350
|
+
unneeded_vms.each do |vm_model|
|
|
358
351
|
pool.process do
|
|
359
|
-
@event_log.track(
|
|
360
|
-
@logger.info("Delete unneeded VM #{
|
|
361
|
-
@cloud.delete_vm(
|
|
362
|
-
|
|
352
|
+
@event_log.track(vm_model.cid) do
|
|
353
|
+
@logger.info("Delete unneeded VM #{vm_model.cid}")
|
|
354
|
+
@cloud.delete_vm(vm_model.cid)
|
|
355
|
+
vm_model.destroy
|
|
363
356
|
end
|
|
364
357
|
end
|
|
365
358
|
end
|
|
@@ -118,7 +118,7 @@ module Bosh::Director
|
|
|
118
118
|
job_spec.recursive_merge!(state_overrides)
|
|
119
119
|
end
|
|
120
120
|
|
|
121
|
-
@deployment.add_job(Job.parse(@deployment, job_spec, @event_log))
|
|
121
|
+
@deployment.add_job(Job.parse(@deployment, job_spec, @event_log, @logger))
|
|
122
122
|
end
|
|
123
123
|
end
|
|
124
124
|
end
|
|
@@ -29,10 +29,10 @@ module Bosh::Director
|
|
|
29
29
|
attr_accessor :state
|
|
30
30
|
|
|
31
31
|
# @return [Hash] current state as provided by the BOSH Agent
|
|
32
|
-
|
|
32
|
+
attr_reader :current_state
|
|
33
33
|
|
|
34
|
-
# @return [DeploymentPlan::
|
|
35
|
-
attr_reader :
|
|
34
|
+
# @return [DeploymentPlan::Vm] Associated resource pool VM
|
|
35
|
+
attr_reader :vm
|
|
36
36
|
|
|
37
37
|
# @return [Boolean] true if this instance needs to be recreated
|
|
38
38
|
attr_accessor :recreate
|
|
@@ -40,18 +40,18 @@ module Bosh::Director
|
|
|
40
40
|
# @return [Boolean] true if this instance needs to be restarted
|
|
41
41
|
attr_accessor :restart
|
|
42
42
|
|
|
43
|
-
##
|
|
44
43
|
# Creates a new instance specification based on the job and index.
|
|
45
|
-
#
|
|
46
44
|
# @param [DeploymentPlan::Job] job associated job
|
|
47
45
|
# @param [Integer] index index for this instance
|
|
48
|
-
def initialize(job, index)
|
|
46
|
+
def initialize(job, index, logger)
|
|
49
47
|
@job = job
|
|
50
48
|
@index = index
|
|
49
|
+
@logger = logger
|
|
50
|
+
|
|
51
51
|
@model = nil
|
|
52
52
|
@configuration_hash = nil
|
|
53
53
|
@template_hashes = nil
|
|
54
|
-
@
|
|
54
|
+
@vm = nil
|
|
55
55
|
@current_state = nil
|
|
56
56
|
|
|
57
57
|
@network_reservations = {}
|
|
@@ -72,33 +72,84 @@ module Bosh::Director
|
|
|
72
72
|
"#{@job.name}/#{@index}"
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
#
|
|
76
|
-
# @return [void]
|
|
77
|
-
def use_model(model)
|
|
78
|
-
if @model
|
|
79
|
-
raise DirectorError, 'Instance model is already bound'
|
|
80
|
-
end
|
|
81
|
-
@model = model
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Looks up a DB model for this instance, creates one if doesn't exist
|
|
85
|
-
# yet.
|
|
75
|
+
# Looks up a DB model for this instance, creates one if doesn't exist yet.
|
|
86
76
|
# @return [void]
|
|
87
77
|
def bind_model
|
|
88
78
|
@model ||= find_or_create_model
|
|
89
79
|
end
|
|
90
80
|
|
|
91
81
|
# Looks up instance model in DB and binds it to this instance spec.
|
|
92
|
-
# Instance model is created if it's not found in DB. New
|
|
82
|
+
# Instance model is created if it's not found in DB. New VM is
|
|
93
83
|
# allocated if instance DB record doesn't reference one.
|
|
94
84
|
# @return [void]
|
|
95
85
|
def bind_unallocated_vm
|
|
96
86
|
bind_model
|
|
97
87
|
if @model.vm.nil?
|
|
98
|
-
|
|
88
|
+
allocate_vm
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
##
|
|
93
|
+
# Updates this domain object to reflect an existing instance running on an existing vm
|
|
94
|
+
def bind_existing_instance(instance_model, state, reservations)
|
|
95
|
+
raise DirectorError, "Instance `#{self}' model is already bound" if @model
|
|
96
|
+
@model = instance_model
|
|
97
|
+
@current_state = state
|
|
98
|
+
|
|
99
|
+
take_network_reservations(reservations)
|
|
100
|
+
add_allocated_vm(instance_model.vm, state)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def apply_partial_vm_state
|
|
104
|
+
@logger.info('Applying partial VM state')
|
|
105
|
+
|
|
106
|
+
state = @vm.current_state
|
|
107
|
+
state['job'] = job.spec
|
|
108
|
+
state['index'] = index
|
|
109
|
+
|
|
110
|
+
# Apply the assignment to the VM
|
|
111
|
+
agent = AgentClient.with_defaults(@vm.model.agent_id)
|
|
112
|
+
agent.apply(state)
|
|
113
|
+
|
|
114
|
+
# Our assumption here is that director database access
|
|
115
|
+
# is much less likely to fail than VM agent communication
|
|
116
|
+
# so we only update database after we see a successful agent apply.
|
|
117
|
+
# If database update fails subsequent deploy will try to
|
|
118
|
+
# assign a new VM to this instance which is ok.
|
|
119
|
+
@vm.model.db.transaction do
|
|
120
|
+
@vm.model.update(:apply_spec => state)
|
|
121
|
+
@model.update(:vm => @vm.model)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
@current_state = state
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def apply_vm_state
|
|
128
|
+
@logger.info('Applying VM state')
|
|
129
|
+
|
|
130
|
+
state = {
|
|
131
|
+
'deployment' => @job.deployment.name,
|
|
132
|
+
'networks' => network_settings,
|
|
133
|
+
'resource_pool' => @job.resource_pool.spec,
|
|
134
|
+
'job' => @job.spec,
|
|
135
|
+
'index' => @index,
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if disk_size > 0
|
|
139
|
+
state['persistent_disk'] = disk_size
|
|
99
140
|
end
|
|
141
|
+
|
|
142
|
+
@model.vm.update(:apply_spec => state)
|
|
143
|
+
|
|
144
|
+
agent = AgentClient.with_defaults(@model.vm.agent_id)
|
|
145
|
+
agent.apply(state)
|
|
146
|
+
|
|
147
|
+
# Agent will potentially return modified version of state
|
|
148
|
+
# with resolved dynamic networks information
|
|
149
|
+
@current_state = agent.get_state
|
|
100
150
|
end
|
|
101
151
|
|
|
152
|
+
##
|
|
102
153
|
# Syncs instance state with instance model in DB. This is needed because
|
|
103
154
|
# not all instance states are available in the deployment manifest and we
|
|
104
155
|
# we cannot really persist this data in the agent state (as VM might be
|
|
@@ -138,18 +189,6 @@ module Bosh::Director
|
|
|
138
189
|
@network_reservations[name] = reservation
|
|
139
190
|
end
|
|
140
191
|
|
|
141
|
-
##
|
|
142
|
-
# Take any existing valid network reservations
|
|
143
|
-
#
|
|
144
|
-
# @param [Hash<String, NetworkReservation>] reservations
|
|
145
|
-
# @return [void]
|
|
146
|
-
def take_network_reservations(reservations)
|
|
147
|
-
reservations.each do |name, provided_reservation|
|
|
148
|
-
reservation = @network_reservations[name]
|
|
149
|
-
reservation.take(provided_reservation) if reservation
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
|
|
153
192
|
##
|
|
154
193
|
# @return [Hash] BOSH network settings used for Agent apply call
|
|
155
194
|
def network_settings
|
|
@@ -220,8 +259,7 @@ module Bosh::Director
|
|
|
220
259
|
end
|
|
221
260
|
|
|
222
261
|
##
|
|
223
|
-
# @return [Boolean] returns true if the persistent disk is attached to the
|
|
224
|
-
# VM
|
|
262
|
+
# @return [Boolean] returns true if the persistent disk is attached to the VM
|
|
225
263
|
def disk_currently_attached?
|
|
226
264
|
current_state['persistent_disk'].to_i > 0
|
|
227
265
|
end
|
|
@@ -233,8 +271,7 @@ module Bosh::Director
|
|
|
233
271
|
end
|
|
234
272
|
|
|
235
273
|
##
|
|
236
|
-
# @return [Boolean] returns true if the expected resource pool differs
|
|
237
|
-
# from the one provided by the VM
|
|
274
|
+
# @return [Boolean] returns true if the expected resource pool differs from the one provided by the VM
|
|
238
275
|
def resource_pool_changed?
|
|
239
276
|
if @recreate || @job.deployment.recreate
|
|
240
277
|
return true
|
|
@@ -251,8 +288,7 @@ module Bosh::Director
|
|
|
251
288
|
# doesn't persist VM env to the version that does, there needs to
|
|
252
289
|
# be at least one deployment that recreates all VMs before the following
|
|
253
290
|
# code path gets exercised.
|
|
254
|
-
if @model && @model.vm && @model.vm.env &&
|
|
255
|
-
@job.resource_pool.env != @model.vm.env
|
|
291
|
+
if @model && @model.vm && @model.vm.env && @job.resource_pool.env != @model.vm.env
|
|
256
292
|
return true
|
|
257
293
|
end
|
|
258
294
|
|
|
@@ -270,6 +306,8 @@ module Bosh::Director
|
|
|
270
306
|
# @return [Boolean] returns true if the expected job configuration differs
|
|
271
307
|
# from the one provided by the VM
|
|
272
308
|
def job_changed?
|
|
309
|
+
return true if @current_state.nil?
|
|
310
|
+
|
|
273
311
|
job_spec = @job.spec
|
|
274
312
|
if job_spec != @current_state['job']
|
|
275
313
|
# The agent job spec could be in legacy form. job_spec cannot be,
|
|
@@ -330,8 +368,7 @@ module Bosh::Director
|
|
|
330
368
|
end
|
|
331
369
|
|
|
332
370
|
##
|
|
333
|
-
# @return [Set<Symbol>] returns a set of all of the specification
|
|
334
|
-
# differences
|
|
371
|
+
# @return [Set<Symbol>] returns a set of all of the specification differences
|
|
335
372
|
def changes
|
|
336
373
|
changes = Set.new
|
|
337
374
|
unless @state == 'detached' && @current_state.nil?
|
|
@@ -351,7 +388,6 @@ module Bosh::Director
|
|
|
351
388
|
##
|
|
352
389
|
# Instance spec that's passed to the VM during the BOSH Agent apply call.
|
|
353
390
|
# It's what's used for comparing the expected vs the actual state.
|
|
354
|
-
#
|
|
355
391
|
# @return [Hash<String, Object>] instance spec
|
|
356
392
|
def spec
|
|
357
393
|
spec = {
|
|
@@ -399,31 +435,57 @@ module Bosh::Director
|
|
|
399
435
|
end
|
|
400
436
|
end
|
|
401
437
|
|
|
402
|
-
# Allocates an
|
|
403
|
-
# instance to that idle VM.
|
|
438
|
+
# Allocates an VM in this job resource pool and binds current instance to that VM.
|
|
404
439
|
# @return [void]
|
|
405
|
-
def
|
|
440
|
+
def allocate_vm
|
|
406
441
|
resource_pool = @job.resource_pool
|
|
407
|
-
|
|
442
|
+
vm = resource_pool.allocate_vm
|
|
408
443
|
network = resource_pool.network
|
|
409
444
|
|
|
410
|
-
if
|
|
445
|
+
if vm.model
|
|
411
446
|
# There's already a resource pool VM that can become our instance,
|
|
412
447
|
# so we can try to reuse its reservation
|
|
413
448
|
instance_reservation = @network_reservations[network.name]
|
|
414
449
|
if instance_reservation
|
|
415
|
-
instance_reservation.take(
|
|
450
|
+
instance_reservation.take(vm.network_reservation)
|
|
416
451
|
end
|
|
417
452
|
else
|
|
418
453
|
# VM is not created yet: let's just make it reference this instance
|
|
419
454
|
# so later it knows what it needs to become
|
|
420
|
-
|
|
455
|
+
vm.bound_instance = self
|
|
456
|
+
|
|
421
457
|
# this also means we no longer need previous VM network reservation
|
|
422
458
|
# (instance has its own)
|
|
423
|
-
|
|
459
|
+
vm.release_reservation
|
|
424
460
|
end
|
|
425
461
|
|
|
426
|
-
@
|
|
462
|
+
@vm = vm
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
private
|
|
466
|
+
|
|
467
|
+
##
|
|
468
|
+
# Take any existing valid network reservations
|
|
469
|
+
# @param [Hash<String, NetworkReservation>] reservations
|
|
470
|
+
# @return [void]
|
|
471
|
+
def take_network_reservations(reservations)
|
|
472
|
+
@logger.debug("Copying job instance `#{self}' network reservations")
|
|
473
|
+
reservations.each do |name, provided_reservation|
|
|
474
|
+
reservation = @network_reservations[name]
|
|
475
|
+
reservation.take(provided_reservation) if reservation
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
def add_allocated_vm(vm_model, state)
|
|
480
|
+
resource_pool = @job.resource_pool
|
|
481
|
+
vm = resource_pool.add_allocated_vm
|
|
482
|
+
|
|
483
|
+
@logger.debug("Found VM `#{vm_model.cid}' running job instance `#{self}' in resource pool `#{resource_pool.name}'")
|
|
484
|
+
vm.model = vm_model
|
|
485
|
+
vm.bound_instance = self
|
|
486
|
+
vm.current_state = state
|
|
487
|
+
|
|
488
|
+
@vm = vm
|
|
427
489
|
end
|
|
428
490
|
end
|
|
429
491
|
end
|
|
@@ -25,35 +25,13 @@ module Bosh::Director
|
|
|
25
25
|
|
|
26
26
|
ThreadPool.new(:max_threads => Config.max_threads).wrap do |pool|
|
|
27
27
|
unbound_instances.each do |instance|
|
|
28
|
-
pool.process
|
|
28
|
+
pool.process do
|
|
29
|
+
@event_log.track("#{instance.job.name}/#{instance.index}") do
|
|
30
|
+
instance.apply_partial_vm_state
|
|
31
|
+
end
|
|
32
|
+
end
|
|
29
33
|
end
|
|
30
34
|
end
|
|
31
35
|
end
|
|
32
|
-
|
|
33
|
-
# @param [DeploymentPlan::Instance] instance
|
|
34
|
-
def bind_instance_vm(instance)
|
|
35
|
-
@event_log.track("#{instance.job.name}/#{instance.index}") do
|
|
36
|
-
idle_vm = instance.idle_vm
|
|
37
|
-
|
|
38
|
-
# Apply the assignment to the VM
|
|
39
|
-
agent = AgentClient.with_defaults(idle_vm.vm.agent_id)
|
|
40
|
-
state = idle_vm.current_state
|
|
41
|
-
state['job'] = instance.job.spec
|
|
42
|
-
state['index'] = instance.index
|
|
43
|
-
agent.apply(state)
|
|
44
|
-
|
|
45
|
-
# Our assumption here is that director database access
|
|
46
|
-
# is much less likely to fail than VM agent communication
|
|
47
|
-
# so we only update database after we see a successful agent apply.
|
|
48
|
-
# If database update fails subsequent deploy will try to
|
|
49
|
-
# assign a new VM to this instance which is ok.
|
|
50
|
-
idle_vm.vm.db.transaction do
|
|
51
|
-
idle_vm.vm.update(:apply_spec => state)
|
|
52
|
-
instance.model.update(:vm => idle_vm.vm)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
instance.current_state = state
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
36
|
end
|
|
59
37
|
end
|
|
@@ -68,12 +68,13 @@ module Bosh::Director
|
|
|
68
68
|
|
|
69
69
|
attr_accessor :all_properties
|
|
70
70
|
|
|
71
|
-
# @param [Bosh::Director::DeploymentPlan::Planner]
|
|
72
|
-
# deployment Deployment plan
|
|
71
|
+
# @param [Bosh::Director::DeploymentPlan::Planner] deployment Deployment plan
|
|
73
72
|
# @param [Hash] job_spec Raw job spec from the deployment manifest
|
|
73
|
+
# @param [Bosh::Director::EventLog::Log] event_log Event log for recording deprecations
|
|
74
|
+
# @param [Logger] logger Log for director logging
|
|
74
75
|
# @return [Bosh::Director::DeploymentPlan::Job]
|
|
75
|
-
def self.parse(deployment, job_spec, event_log)
|
|
76
|
-
parser = JobSpecParser.new(deployment, event_log)
|
|
76
|
+
def self.parse(deployment, job_spec, event_log, logger)
|
|
77
|
+
parser = JobSpecParser.new(deployment, event_log, logger)
|
|
77
78
|
parser.parse(job_spec)
|
|
78
79
|
end
|
|
79
80
|
|
|
@@ -234,9 +235,7 @@ module Bosh::Director
|
|
|
234
235
|
unless reservation.reserved?
|
|
235
236
|
network = @deployment.network(net_name)
|
|
236
237
|
network.reserve!(reservation, "`#{name}/#{instance.index}'")
|
|
237
|
-
if instance.
|
|
238
|
-
instance.idle_vm.use_reservation(reservation)
|
|
239
|
-
end
|
|
238
|
+
instance.vm.use_reservation(reservation) if instance.vm
|
|
240
239
|
end
|
|
241
240
|
end
|
|
242
241
|
end
|
|
@@ -9,9 +9,10 @@ module Bosh::Director
|
|
|
9
9
|
include IpUtil
|
|
10
10
|
|
|
11
11
|
# @param [Bosh::Director::DeploymentPlan] deployment Deployment plan
|
|
12
|
-
def initialize(deployment, event_log)
|
|
12
|
+
def initialize(deployment, event_log, logger)
|
|
13
13
|
@deployment = deployment
|
|
14
14
|
@event_log = event_log
|
|
15
|
+
@logger = logger
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
# @param [Hash] job_spec Raw job spec from the deployment manifest
|
|
@@ -222,7 +223,7 @@ module Bosh::Director
|
|
|
222
223
|
@job.resource_pool.reserve_capacity(job_size)
|
|
223
224
|
end
|
|
224
225
|
job_size.times do |index|
|
|
225
|
-
@job.instances[index] = Instance.new(@job, index)
|
|
226
|
+
@job.instances[index] = Instance.new(@job, index, @logger)
|
|
226
227
|
end
|
|
227
228
|
end
|
|
228
229
|
|
|
@@ -32,9 +32,6 @@ module Bosh::Director
|
|
|
32
32
|
# @return [Array<DeploymentPlan::IdleVm] List of allocated idle VMs
|
|
33
33
|
attr_reader :allocated_vms
|
|
34
34
|
|
|
35
|
-
# @return [Integer] Number of active resource pool VMs
|
|
36
|
-
attr_reader :active_vm_count
|
|
37
|
-
|
|
38
35
|
# @return [Integer] Number of VMs reserved
|
|
39
36
|
attr_reader :reserved_capacity
|
|
40
37
|
|
|
@@ -68,7 +65,6 @@ module Bosh::Director
|
|
|
68
65
|
|
|
69
66
|
@idle_vms = []
|
|
70
67
|
@allocated_vms = []
|
|
71
|
-
@active_vm_count = 0
|
|
72
68
|
@reserved_capacity = 0
|
|
73
69
|
@reserved_errand_capacity = 0
|
|
74
70
|
end
|
|
@@ -83,7 +79,7 @@ module Bosh::Director
|
|
|
83
79
|
}
|
|
84
80
|
end
|
|
85
81
|
|
|
86
|
-
# Creates
|
|
82
|
+
# Creates idle VMs for any missing resource pool VMs and reserves
|
|
87
83
|
# dynamic networks for all idle VMs.
|
|
88
84
|
# @return [void]
|
|
89
85
|
def process_idle_vms
|
|
@@ -107,34 +103,40 @@ module Bosh::Director
|
|
|
107
103
|
reservation
|
|
108
104
|
end
|
|
109
105
|
|
|
110
|
-
# Adds a new VM to
|
|
106
|
+
# Adds a new VM to idle_vms
|
|
111
107
|
def add_idle_vm
|
|
112
|
-
|
|
108
|
+
@logger.info("ResourcePool `#{name}' - Adding idle VM (index=#{@idle_vms.size})")
|
|
109
|
+
idle_vm = Vm.new(self)
|
|
113
110
|
@idle_vms << idle_vm
|
|
114
111
|
idle_vm
|
|
115
112
|
end
|
|
116
113
|
|
|
117
114
|
def allocate_vm
|
|
118
|
-
if @idle_vms.empty?
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
"Resource pool `#{@name}' has no more VMs to allocate"
|
|
124
|
-
end
|
|
115
|
+
if @idle_vms.empty? && dynamically_sized?
|
|
116
|
+
vm = Vm.new(self)
|
|
117
|
+
else
|
|
118
|
+
vm = @idle_vms.pop
|
|
119
|
+
raise ResourcePoolNotEnoughCapacity, "Resource pool `#{@name}' has no more VMs to allocate" if vm.nil?
|
|
125
120
|
end
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
121
|
+
|
|
122
|
+
add_allocated_vm(vm)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Adds an existing VM to allocated_vms
|
|
126
|
+
def add_allocated_vm(vm=nil)
|
|
127
|
+
vm ||= Vm.new(self)
|
|
128
|
+
@logger.info("ResourcePool `#{name}' - Adding allocated VM (index=#{@allocated_vms.size})")
|
|
129
|
+
@allocated_vms << vm
|
|
130
|
+
vm
|
|
129
131
|
end
|
|
130
132
|
|
|
131
|
-
def deallocate_vm(
|
|
132
|
-
deallocated_vm = @allocated_vms.find { |
|
|
133
|
+
def deallocate_vm(vm_cid)
|
|
134
|
+
deallocated_vm = @allocated_vms.find { |vm| vm.model.cid == vm_cid }
|
|
133
135
|
if deallocated_vm.nil?
|
|
134
|
-
raise DirectorError, "Resource pool `#{@name}' does not contain an allocated VM with the cid `#{
|
|
136
|
+
raise DirectorError, "Resource pool `#{@name}' does not contain an allocated VM with the cid `#{vm_cid}'"
|
|
135
137
|
end
|
|
136
138
|
|
|
137
|
-
@logger.info("Deallocating VM: #{deallocated_vm.
|
|
139
|
+
@logger.info("ResourcePool `#{name}' - Deallocating VM: #{deallocated_vm.model.cid}")
|
|
138
140
|
@allocated_vms.delete(deallocated_vm)
|
|
139
141
|
|
|
140
142
|
add_idle_vm unless dynamically_sized? # don't refill if dynamically sized
|
|
@@ -142,12 +144,6 @@ module Bosh::Director
|
|
|
142
144
|
nil
|
|
143
145
|
end
|
|
144
146
|
|
|
145
|
-
# "Active" VM is a VM that is currently running a job
|
|
146
|
-
# @return [void]
|
|
147
|
-
def mark_active_vm
|
|
148
|
-
@active_vm_count += 1
|
|
149
|
-
end
|
|
150
|
-
|
|
151
147
|
# Checks if there is enough capacity to run _extra_ N VMs,
|
|
152
148
|
# raise error if not enough capacity
|
|
153
149
|
# @raise [ResourcePoolNotEnoughCapacity]
|
|
@@ -177,18 +173,26 @@ module Bosh::Director
|
|
|
177
173
|
end
|
|
178
174
|
end
|
|
179
175
|
|
|
180
|
-
|
|
181
|
-
|
|
176
|
+
# Returns a number of VMs that need to be deleted in order to bring
|
|
177
|
+
# this resource pool to the desired size
|
|
178
|
+
# @return [Integer]
|
|
179
|
+
def extra_vm_count
|
|
180
|
+
return 0 if dynamically_sized?
|
|
181
|
+
@idle_vms.size + @allocated_vms.size - @size
|
|
182
182
|
end
|
|
183
183
|
|
|
184
184
|
private
|
|
185
185
|
|
|
186
|
+
def dynamically_sized?
|
|
187
|
+
@size.nil?
|
|
188
|
+
end
|
|
189
|
+
|
|
186
190
|
# Returns a number of VMs that need to be created in order to bring
|
|
187
|
-
# this resource pool to
|
|
191
|
+
# this resource pool to the desired size
|
|
188
192
|
# @return [Integer]
|
|
189
193
|
def missing_vm_count
|
|
190
194
|
return 0 if dynamically_sized?
|
|
191
|
-
@size - @
|
|
195
|
+
@size - @allocated_vms.size - @idle_vms.size
|
|
192
196
|
end
|
|
193
197
|
end
|
|
194
198
|
end
|
|
@@ -7,15 +7,15 @@ module Bosh::Director
|
|
|
7
7
|
# reserved for an instance to minimize the number of CPI operations
|
|
8
8
|
# (network & storage) required for the VM to match the instance
|
|
9
9
|
# requirements.
|
|
10
|
-
class
|
|
10
|
+
class Vm
|
|
11
11
|
# @return [DeploymentPlan::ResourcePool] Associated resource pool
|
|
12
12
|
attr_reader :resource_pool
|
|
13
13
|
|
|
14
14
|
# @return [NetworkReservation] VM network reservation
|
|
15
15
|
attr_accessor :network_reservation
|
|
16
16
|
|
|
17
|
-
# @return [Models::Vm] Associated model
|
|
18
|
-
attr_accessor :
|
|
17
|
+
# @return [Models::Vm] Associated DB model
|
|
18
|
+
attr_accessor :model
|
|
19
19
|
|
|
20
20
|
# @return [Hash] Current state as provided by the BOSH Agent
|
|
21
21
|
attr_writer :current_state
|
|
@@ -38,7 +38,7 @@ module Bosh::Director
|
|
|
38
38
|
@current_state = nil
|
|
39
39
|
@bound_instance = nil
|
|
40
40
|
@network_reservation = nil
|
|
41
|
-
@
|
|
41
|
+
@model = nil
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
#
|
|
@@ -98,7 +98,7 @@ module Bosh::Director
|
|
|
98
98
|
def resource_pool_changed?
|
|
99
99
|
return true if resource_pool.spec != @current_state['resource_pool']
|
|
100
100
|
return true if resource_pool.deployment_plan.recreate
|
|
101
|
-
return true if @
|
|
101
|
+
return true if @model && @model.env != resource_pool.env
|
|
102
102
|
|
|
103
103
|
false
|
|
104
104
|
end
|
|
@@ -110,8 +110,9 @@ module Bosh::Director
|
|
|
110
110
|
resource_pool_changed? || networks_changed?
|
|
111
111
|
end
|
|
112
112
|
|
|
113
|
+
#TODO: rename 'clean'
|
|
113
114
|
def clean_vm
|
|
114
|
-
self.
|
|
115
|
+
self.model = nil
|
|
115
116
|
self.current_state = nil
|
|
116
117
|
end
|
|
117
118
|
end
|
|
@@ -52,7 +52,7 @@ module Bosh::Director
|
|
|
52
52
|
# @return [void]
|
|
53
53
|
def deallocate_vms
|
|
54
54
|
@logger.info('Deallocating errand VMs')
|
|
55
|
-
instance_vm_cids = @job.instances.map { |
|
|
55
|
+
instance_vm_cids = @job.instances.map { |instance| instance.model.vm.cid }
|
|
56
56
|
instance_vm_cids.each { |cid| @job.resource_pool.deallocate_vm(cid) }
|
|
57
57
|
end
|
|
58
58
|
end
|
|
@@ -42,8 +42,8 @@ module Bosh::Director
|
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
@instance.apply_vm_state
|
|
46
|
+
@job_renderer.render_job_instance(@instance)
|
|
47
47
|
|
|
48
48
|
[@vm_model, @agent_client]
|
|
49
49
|
end
|
|
@@ -183,41 +183,5 @@ module Bosh::Director
|
|
|
183
183
|
@cloud.detach_disk(@vm_model.cid, @instance.model.persistent_disk_cid)
|
|
184
184
|
end
|
|
185
185
|
end
|
|
186
|
-
|
|
187
|
-
class VmStateApplier
|
|
188
|
-
def initialize(instance, vm_model, agent_client, job_renderer, logger)
|
|
189
|
-
@instance = instance
|
|
190
|
-
@vm_model = vm_model
|
|
191
|
-
@agent_client = agent_client
|
|
192
|
-
@job_renderer = job_renderer
|
|
193
|
-
@logger = logger
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
def apply
|
|
197
|
-
@logger.info('Applying VM state')
|
|
198
|
-
|
|
199
|
-
state = {
|
|
200
|
-
'deployment' => @instance.job.deployment.name,
|
|
201
|
-
'networks' => @instance.network_settings,
|
|
202
|
-
'resource_pool' => @instance.job.resource_pool.spec,
|
|
203
|
-
'job' => @instance.job.spec,
|
|
204
|
-
'index' => @instance.index,
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if @instance.disk_size > 0
|
|
208
|
-
state['persistent_disk'] = @instance.disk_size
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
@vm_model.update(:apply_spec => state)
|
|
212
|
-
|
|
213
|
-
@agent_client.apply(state)
|
|
214
|
-
|
|
215
|
-
# Agent will potentially return modified version of state
|
|
216
|
-
# with resolved dynamic networks information
|
|
217
|
-
@instance.current_state = @agent_client.get_state
|
|
218
|
-
|
|
219
|
-
@job_renderer.render_job_instance(@instance)
|
|
220
|
-
end
|
|
221
|
-
end
|
|
222
186
|
end
|
|
223
187
|
end
|
|
@@ -12,26 +12,26 @@ module Bosh::Director
|
|
|
12
12
|
#
|
|
13
13
|
# @param [ThreadPool] thread_pool Thread pool that will be used to
|
|
14
14
|
# parallelize the operation
|
|
15
|
-
# @yield [
|
|
15
|
+
# @yield [VirtualMachine] filter for which missing VMs to create
|
|
16
16
|
def create_missing_vms(thread_pool)
|
|
17
17
|
counter = 0
|
|
18
18
|
vms_to_process = []
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
next if
|
|
22
|
-
if !block_given? || yield(
|
|
20
|
+
each_vm do |vm|
|
|
21
|
+
next if vm.model
|
|
22
|
+
if !block_given? || yield(vm)
|
|
23
23
|
counter += 1
|
|
24
|
-
vms_to_process <<
|
|
24
|
+
vms_to_process << vm
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
@logger.info("Creating #{counter} missing VMs")
|
|
29
|
-
vms_to_process.each_with_index do |
|
|
29
|
+
vms_to_process.each_with_index do |vm, index|
|
|
30
30
|
thread_pool.process do
|
|
31
31
|
@event_log.track("#{@resource_pool.name}/#{index}") do
|
|
32
32
|
with_thread_name("create_missing_vm(#{@resource_pool.name}, #{index}/#{counter})") do
|
|
33
33
|
@logger.info("Creating missing VM")
|
|
34
|
-
create_missing_vm(
|
|
34
|
+
create_missing_vm(vm)
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
end
|
|
@@ -41,60 +41,60 @@ module Bosh::Director
|
|
|
41
41
|
# Creates missing VMs that have bound instances
|
|
42
42
|
# (as opposed to missing resource pool VMs)
|
|
43
43
|
def create_bound_missing_vms(thread_pool)
|
|
44
|
-
create_missing_vms(thread_pool) { |
|
|
44
|
+
create_missing_vms(thread_pool) { |vm| !vm.bound_instance.nil? }
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
def create_missing_vm(
|
|
47
|
+
def create_missing_vm(vm)
|
|
48
48
|
deployment = @resource_pool.deployment_plan.model
|
|
49
49
|
stemcell = @resource_pool.stemcell.model
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
vm_model = VmCreator.new.create(deployment, stemcell, @resource_pool.cloud_properties,
|
|
52
|
+
vm.network_settings, nil, @resource_pool.env)
|
|
53
53
|
|
|
54
|
-
agent = AgentClient.with_defaults(
|
|
54
|
+
agent = AgentClient.with_defaults(vm_model.agent_id)
|
|
55
55
|
agent.wait_until_ready
|
|
56
56
|
|
|
57
|
-
update_state(agent,
|
|
57
|
+
update_state(agent, vm_model, vm)
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
vm.model = vm_model
|
|
60
|
+
vm.current_state = agent.get_state
|
|
61
61
|
rescue Exception => e
|
|
62
62
|
@logger.info("Cleaning up the created VM due to an error: #{e}")
|
|
63
63
|
begin
|
|
64
|
-
@cloud.delete_vm(
|
|
65
|
-
|
|
64
|
+
@cloud.delete_vm(vm_model.cid) if vm_model && vm_model.cid
|
|
65
|
+
vm_model.destroy if vm_model && vm_model.id
|
|
66
66
|
rescue Exception
|
|
67
|
-
@logger.info("Could not cleanup VM: #{
|
|
67
|
+
@logger.info("Could not cleanup VM: #{vm_model.cid}") if vm_model
|
|
68
68
|
end
|
|
69
69
|
raise e
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
-
def update_state(agent,
|
|
72
|
+
def update_state(agent, vm_model, vm)
|
|
73
73
|
state = {
|
|
74
74
|
"deployment" => @resource_pool.deployment_plan.name,
|
|
75
75
|
"resource_pool" => @resource_pool.spec,
|
|
76
|
-
"networks" =>
|
|
76
|
+
"networks" => vm.network_settings
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
vm_model.update(:apply_spec => state)
|
|
80
80
|
agent.apply(state)
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
# Deletes extra VMs in a resource pool
|
|
84
84
|
# @param thread_pool Thread pool used to parallelize delete operations
|
|
85
85
|
def delete_extra_vms(thread_pool)
|
|
86
|
-
count = extra_vm_count
|
|
86
|
+
count = @resource_pool.extra_vm_count
|
|
87
87
|
@logger.info("Deleting #{count} extra VMs")
|
|
88
88
|
|
|
89
89
|
count.times do
|
|
90
|
-
|
|
91
|
-
vm_cid =
|
|
90
|
+
vm = @resource_pool.idle_vms.shift
|
|
91
|
+
vm_cid = vm.model.cid
|
|
92
92
|
|
|
93
93
|
thread_pool.process do
|
|
94
94
|
@event_log.track("#{@resource_pool.name}/#{vm_cid}") do
|
|
95
95
|
@logger.info("Deleting extra VM: #{vm_cid}")
|
|
96
96
|
@cloud.delete_vm(vm_cid)
|
|
97
|
-
|
|
97
|
+
vm.model.destroy
|
|
98
98
|
end
|
|
99
99
|
end
|
|
100
100
|
end
|
|
@@ -107,9 +107,9 @@ module Bosh::Director
|
|
|
107
107
|
|
|
108
108
|
@logger.info("Deleting #{count} outdated idle VMs")
|
|
109
109
|
|
|
110
|
-
@resource_pool.idle_vms.each do |
|
|
111
|
-
next unless
|
|
112
|
-
vm_cid =
|
|
110
|
+
@resource_pool.idle_vms.each do |vm|
|
|
111
|
+
next unless vm.model && vm.changed?
|
|
112
|
+
vm_cid = vm.model.cid
|
|
113
113
|
|
|
114
114
|
thread_pool.process do
|
|
115
115
|
@event_log.track("#{@resource_pool.name}/#{vm_cid}") do
|
|
@@ -118,9 +118,9 @@ module Bosh::Director
|
|
|
118
118
|
with_thread_name("delete_outdated_vm(#{@resource_pool.name}, #{index - 1}/#{count})") do
|
|
119
119
|
@logger.info("Deleting outdated VM: #{vm_cid}")
|
|
120
120
|
@cloud.delete_vm(vm_cid)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
vm_model = vm.model
|
|
122
|
+
vm.clean_vm
|
|
123
|
+
vm_model.destroy
|
|
124
124
|
end
|
|
125
125
|
end
|
|
126
126
|
end
|
|
@@ -134,8 +134,8 @@ module Bosh::Director
|
|
|
134
134
|
def reserve_networks
|
|
135
135
|
network = @resource_pool.network
|
|
136
136
|
|
|
137
|
-
|
|
138
|
-
unless
|
|
137
|
+
each_vm_with_index do |vm, index|
|
|
138
|
+
unless vm.network_reservation
|
|
139
139
|
reservation = NetworkReservation.new(
|
|
140
140
|
:type => NetworkReservation::DYNAMIC)
|
|
141
141
|
network.reserve(reservation)
|
|
@@ -153,7 +153,7 @@ module Bosh::Director
|
|
|
153
153
|
end
|
|
154
154
|
end
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
vm.network_reservation = reservation
|
|
157
157
|
end
|
|
158
158
|
end
|
|
159
159
|
end
|
|
@@ -162,39 +162,35 @@ module Bosh::Director
|
|
|
162
162
|
SecureRandom.uuid
|
|
163
163
|
end
|
|
164
164
|
|
|
165
|
-
def
|
|
166
|
-
@resource_pool.allocated_vms.each { |
|
|
167
|
-
@resource_pool.idle_vms.each { |
|
|
165
|
+
def each_vm
|
|
166
|
+
@resource_pool.allocated_vms.each { |vm| yield vm }
|
|
167
|
+
@resource_pool.idle_vms.each { |vm| yield vm }
|
|
168
168
|
end
|
|
169
169
|
|
|
170
|
-
def
|
|
170
|
+
def each_vm_with_index
|
|
171
171
|
index = 0
|
|
172
|
-
|
|
173
|
-
yield(
|
|
172
|
+
each_vm do |vm|
|
|
173
|
+
yield(vm, index)
|
|
174
174
|
index += 1
|
|
175
175
|
end
|
|
176
176
|
end
|
|
177
177
|
|
|
178
178
|
def extra_vm_count
|
|
179
|
-
|
|
180
|
-
@resource_pool.active_vm_count +
|
|
181
|
-
@resource_pool.idle_vms.size +
|
|
182
|
-
@resource_pool.allocated_vms.size -
|
|
183
|
-
@resource_pool.size
|
|
179
|
+
@resource_pool.extra_vm_count
|
|
184
180
|
end
|
|
185
181
|
|
|
186
182
|
def outdated_idle_vm_count
|
|
187
183
|
counter = 0
|
|
188
|
-
@resource_pool.idle_vms.each do |
|
|
189
|
-
counter += 1 if
|
|
184
|
+
@resource_pool.idle_vms.each do |vm|
|
|
185
|
+
counter += 1 if vm.model && vm.changed?
|
|
190
186
|
end
|
|
191
187
|
counter
|
|
192
188
|
end
|
|
193
189
|
|
|
194
190
|
def missing_vm_count
|
|
195
191
|
counter = 0
|
|
196
|
-
|
|
197
|
-
next if
|
|
192
|
+
each_vm do |vm|
|
|
193
|
+
next if vm.model
|
|
198
194
|
counter += 1
|
|
199
195
|
end
|
|
200
196
|
counter
|
|
@@ -202,9 +198,9 @@ module Bosh::Director
|
|
|
202
198
|
|
|
203
199
|
def bound_missing_vm_count
|
|
204
200
|
counter = 0
|
|
205
|
-
|
|
206
|
-
next if
|
|
207
|
-
next if
|
|
201
|
+
each_vm do |vm|
|
|
202
|
+
next if vm.model
|
|
203
|
+
next if vm.bound_instance.nil?
|
|
208
204
|
counter += 1
|
|
209
205
|
end
|
|
210
206
|
counter
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bosh-director
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2624.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2014-
|
|
12
|
+
date: 2014-07-01 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: bcrypt-ruby
|
|
@@ -34,7 +34,7 @@ dependencies:
|
|
|
34
34
|
requirements:
|
|
35
35
|
- - ~>
|
|
36
36
|
- !ruby/object:Gem::Version
|
|
37
|
-
version: 1.
|
|
37
|
+
version: 1.2624.0
|
|
38
38
|
type: :runtime
|
|
39
39
|
prerelease: false
|
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -42,7 +42,7 @@ dependencies:
|
|
|
42
42
|
requirements:
|
|
43
43
|
- - ~>
|
|
44
44
|
- !ruby/object:Gem::Version
|
|
45
|
-
version: 1.
|
|
45
|
+
version: 1.2624.0
|
|
46
46
|
- !ruby/object:Gem::Dependency
|
|
47
47
|
name: bosh-core
|
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -50,7 +50,7 @@ dependencies:
|
|
|
50
50
|
requirements:
|
|
51
51
|
- - ~>
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: 1.
|
|
53
|
+
version: 1.2624.0
|
|
54
54
|
type: :runtime
|
|
55
55
|
prerelease: false
|
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -58,7 +58,7 @@ dependencies:
|
|
|
58
58
|
requirements:
|
|
59
59
|
- - ~>
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: 1.
|
|
61
|
+
version: 1.2624.0
|
|
62
62
|
- !ruby/object:Gem::Dependency
|
|
63
63
|
name: bosh-director-core
|
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -66,7 +66,7 @@ dependencies:
|
|
|
66
66
|
requirements:
|
|
67
67
|
- - ~>
|
|
68
68
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: 1.
|
|
69
|
+
version: 1.2624.0
|
|
70
70
|
type: :runtime
|
|
71
71
|
prerelease: false
|
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -74,7 +74,7 @@ dependencies:
|
|
|
74
74
|
requirements:
|
|
75
75
|
- - ~>
|
|
76
76
|
- !ruby/object:Gem::Version
|
|
77
|
-
version: 1.
|
|
77
|
+
version: 1.2624.0
|
|
78
78
|
- !ruby/object:Gem::Dependency
|
|
79
79
|
name: bosh_common
|
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -82,7 +82,7 @@ dependencies:
|
|
|
82
82
|
requirements:
|
|
83
83
|
- - ~>
|
|
84
84
|
- !ruby/object:Gem::Version
|
|
85
|
-
version: 1.
|
|
85
|
+
version: 1.2624.0
|
|
86
86
|
type: :runtime
|
|
87
87
|
prerelease: false
|
|
88
88
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -90,7 +90,7 @@ dependencies:
|
|
|
90
90
|
requirements:
|
|
91
91
|
- - ~>
|
|
92
92
|
- !ruby/object:Gem::Version
|
|
93
|
-
version: 1.
|
|
93
|
+
version: 1.2624.0
|
|
94
94
|
- !ruby/object:Gem::Dependency
|
|
95
95
|
name: bosh_cpi
|
|
96
96
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -98,7 +98,7 @@ dependencies:
|
|
|
98
98
|
requirements:
|
|
99
99
|
- - ~>
|
|
100
100
|
- !ruby/object:Gem::Version
|
|
101
|
-
version: 1.
|
|
101
|
+
version: 1.2624.0
|
|
102
102
|
type: :runtime
|
|
103
103
|
prerelease: false
|
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -106,7 +106,7 @@ dependencies:
|
|
|
106
106
|
requirements:
|
|
107
107
|
- - ~>
|
|
108
108
|
- !ruby/object:Gem::Version
|
|
109
|
-
version: 1.
|
|
109
|
+
version: 1.2624.0
|
|
110
110
|
- !ruby/object:Gem::Dependency
|
|
111
111
|
name: bosh_openstack_cpi
|
|
112
112
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -114,7 +114,7 @@ dependencies:
|
|
|
114
114
|
requirements:
|
|
115
115
|
- - ~>
|
|
116
116
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: 1.
|
|
117
|
+
version: 1.2624.0
|
|
118
118
|
type: :runtime
|
|
119
119
|
prerelease: false
|
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -122,7 +122,7 @@ dependencies:
|
|
|
122
122
|
requirements:
|
|
123
123
|
- - ~>
|
|
124
124
|
- !ruby/object:Gem::Version
|
|
125
|
-
version: 1.
|
|
125
|
+
version: 1.2624.0
|
|
126
126
|
- !ruby/object:Gem::Dependency
|
|
127
127
|
name: bosh_aws_cpi
|
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -130,7 +130,7 @@ dependencies:
|
|
|
130
130
|
requirements:
|
|
131
131
|
- - ~>
|
|
132
132
|
- !ruby/object:Gem::Version
|
|
133
|
-
version: 1.
|
|
133
|
+
version: 1.2624.0
|
|
134
134
|
type: :runtime
|
|
135
135
|
prerelease: false
|
|
136
136
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -138,7 +138,7 @@ dependencies:
|
|
|
138
138
|
requirements:
|
|
139
139
|
- - ~>
|
|
140
140
|
- !ruby/object:Gem::Version
|
|
141
|
-
version: 1.
|
|
141
|
+
version: 1.2624.0
|
|
142
142
|
- !ruby/object:Gem::Dependency
|
|
143
143
|
name: bosh_vsphere_cpi
|
|
144
144
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -146,7 +146,7 @@ dependencies:
|
|
|
146
146
|
requirements:
|
|
147
147
|
- - ~>
|
|
148
148
|
- !ruby/object:Gem::Version
|
|
149
|
-
version: 1.
|
|
149
|
+
version: 1.2624.0
|
|
150
150
|
type: :runtime
|
|
151
151
|
prerelease: false
|
|
152
152
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -154,7 +154,7 @@ dependencies:
|
|
|
154
154
|
requirements:
|
|
155
155
|
- - ~>
|
|
156
156
|
- !ruby/object:Gem::Version
|
|
157
|
-
version: 1.
|
|
157
|
+
version: 1.2624.0
|
|
158
158
|
- !ruby/object:Gem::Dependency
|
|
159
159
|
name: bosh_warden_cpi
|
|
160
160
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -162,7 +162,7 @@ dependencies:
|
|
|
162
162
|
requirements:
|
|
163
163
|
- - ~>
|
|
164
164
|
- !ruby/object:Gem::Version
|
|
165
|
-
version: 1.
|
|
165
|
+
version: 1.2624.0
|
|
166
166
|
type: :runtime
|
|
167
167
|
prerelease: false
|
|
168
168
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -170,7 +170,7 @@ dependencies:
|
|
|
170
170
|
requirements:
|
|
171
171
|
- - ~>
|
|
172
172
|
- !ruby/object:Gem::Version
|
|
173
|
-
version: 1.
|
|
173
|
+
version: 1.2624.0
|
|
174
174
|
- !ruby/object:Gem::Dependency
|
|
175
175
|
name: bosh_vcloud_cpi
|
|
176
176
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -256,7 +256,7 @@ dependencies:
|
|
|
256
256
|
requirement: !ruby/object:Gem::Requirement
|
|
257
257
|
none: false
|
|
258
258
|
requirements:
|
|
259
|
-
- -
|
|
259
|
+
- - '='
|
|
260
260
|
- !ruby/object:Gem::Version
|
|
261
261
|
version: 0.5.0.beta.12
|
|
262
262
|
type: :runtime
|
|
@@ -264,7 +264,7 @@ dependencies:
|
|
|
264
264
|
version_requirements: !ruby/object:Gem::Requirement
|
|
265
265
|
none: false
|
|
266
266
|
requirements:
|
|
267
|
-
- -
|
|
267
|
+
- - '='
|
|
268
268
|
- !ruby/object:Gem::Version
|
|
269
269
|
version: 0.5.0.beta.12
|
|
270
270
|
- !ruby/object:Gem::Dependency
|
|
@@ -509,7 +509,7 @@ dependencies:
|
|
|
509
509
|
version: '0'
|
|
510
510
|
description: ! 'BOSH Director
|
|
511
511
|
|
|
512
|
-
|
|
512
|
+
03f604'
|
|
513
513
|
email: support@cloudfoundry.com
|
|
514
514
|
executables:
|
|
515
515
|
- bosh-director
|
|
@@ -621,7 +621,6 @@ files:
|
|
|
621
621
|
- lib/bosh/director/deployment_plan/deployment_spec_parser.rb
|
|
622
622
|
- lib/bosh/director/deployment_plan/dns_binder.rb
|
|
623
623
|
- lib/bosh/director/deployment_plan/dynamic_network.rb
|
|
624
|
-
- lib/bosh/director/deployment_plan/idle_vm.rb
|
|
625
624
|
- lib/bosh/director/deployment_plan/instance.rb
|
|
626
625
|
- lib/bosh/director/deployment_plan/instance_vm_binder.rb
|
|
627
626
|
- lib/bosh/director/deployment_plan/job.rb
|
|
@@ -640,6 +639,7 @@ files:
|
|
|
640
639
|
- lib/bosh/director/deployment_plan/update_config.rb
|
|
641
640
|
- lib/bosh/director/deployment_plan/updater.rb
|
|
642
641
|
- lib/bosh/director/deployment_plan/vip_network.rb
|
|
642
|
+
- lib/bosh/director/deployment_plan/vm.rb
|
|
643
643
|
- lib/bosh/director/dns_helper.rb
|
|
644
644
|
- lib/bosh/director/download_helper.rb
|
|
645
645
|
- lib/bosh/director/duration.rb
|
|
@@ -770,7 +770,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
770
770
|
version: '0'
|
|
771
771
|
segments:
|
|
772
772
|
- 0
|
|
773
|
-
hash: -
|
|
773
|
+
hash: -2871542120814616469
|
|
774
774
|
requirements: []
|
|
775
775
|
rubyforge_project:
|
|
776
776
|
rubygems_version: 1.8.23.2
|