Class: Bosh::Director::DeploymentPlan::Instance
- Includes:
- Bosh::Director::DnsHelper
- Defined in:
- lib/bosh/director/deployment_plan/instance.rb
Overview
Represents a single job instance.
Constant Summary
Constants included from Bosh::Director::DnsHelper
Bosh::Director::DnsHelper::SOA, Bosh::Director::DnsHelper::TTL_4H, Bosh::Director::DnsHelper::TTL_5M
Instance Attribute Summary collapse
-
#configuration_hash ⇒ String
Checksum all of the configuration templates.
-
#current_state ⇒ Hash
Current state as provided by the BOSH Agent.
-
#idle_vm ⇒ DeploymentPlan::IdleVm
readonly
Associated resource pool VM.
-
#index ⇒ Integer
readonly
Instance index.
-
#job ⇒ DeploymentPlan::Job
readonly
Associated job.
-
#model ⇒ Models::Instance
readonly
Instance model.
-
#network_reservations ⇒ Hash<String, NetworkReservation>
Network reservations.
-
#recreate ⇒ Boolean
True if this instance needs to be recreated.
- #rendered_templates_archive ⇒ Bosh::Director::Core::Templates::RenderedTemplatesArchive
-
#restart ⇒ Boolean
True if this instance needs to be restarted.
-
#state ⇒ String
Job state.
-
#template_hashes ⇒ Hash
A hash of template SHA1 hashes.
Instance Method Summary collapse
-
#add_network_reservation(name, reservation) ⇒ Object
Adds a new network to this instance.
-
#allocate_idle_vm ⇒ void
Allocates an idle VM in this job resource pool and binds current instance to that idle VM.
-
#bind_model ⇒ void
Looks up a DB model for this instance, creates one if doesn’t exist yet.
-
#bind_unallocated_vm ⇒ void
Looks up instance model in DB and binds it to this instance spec.
-
#changed? ⇒ Boolean
Returns true if the any of the expected specifications differ from the ones provided by the VM.
-
#changes ⇒ Set<Symbol>
Returns a set of all of the specification differences.
-
#configuration_changed? ⇒ Boolean
Returns true if the expected configuration hash differs from the one provided by the VM.
-
#disk_currently_attached? ⇒ Boolean
Returns true if the persistent disk is attached to the VM.
-
#disk_size ⇒ Integer
Persistent disk size.
-
#dns_changed? ⇒ Boolean
Returns true if the DNS records configured for the instance differ from the ones configured on the DNS server.
-
#dns_record_info ⇒ Hash<String, String>
Dns record hash of dns name and IP.
-
#dns_record_name(network_name) ⇒ String
Dns record name.
-
#find_or_create_model ⇒ Models::Instance
Looks up instance model in DB.
-
#initialize(job, index) ⇒ Instance
constructor
Creates a new instance specification based on the job and index.
-
#job_changed? ⇒ Boolean
Returns true if the expected job configuration differs from the one provided by the VM.
-
#network_settings ⇒ Hash
BOSH network settings used for Agent apply call.
-
#networks_changed? ⇒ Boolean
Returns true if the network configuration changed.
-
#packages_changed? ⇒ Boolean
Returns true if the expected packaged of the running instance differ from the ones provided by the VM.
-
#persistent_disk_changed? ⇒ Boolean
Returns true if the expected persistent disk differs from the one currently configured on the VM.
-
#resource_pool_changed? ⇒ Boolean
Returns true if the expected resource pool differs from the one provided by the VM.
-
#spec ⇒ Hash<String, Object>
Instance spec that’s passed to the VM during the BOSH Agent apply call.
-
#state_changed? ⇒ Boolean
Checks if agent view of the instance state is consistent with target instance state.
-
#sync_state_with_db ⇒ void
Syncs instance state with instance model in DB.
-
#take_network_reservations(reservations) ⇒ void
Take any existing valid network reservations.
- #to_s ⇒ Object
- #use_model(model) ⇒ void
Methods included from Bosh::Director::DnsHelper
#add_default_dns_server, #canonical, #default_dns_server, #delete_dns_records, #delete_empty_domain, #dns_domain_name, #dns_ns_record, #dns_servers, #invalid_dns, #reverse_domain, #reverse_host, #update_dns_a_record, #update_dns_ptr_record
Constructor Details
#initialize(job, index) ⇒ Instance
Creates a new instance specification based on the job and index.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 48 def initialize(job, index) @job = job @index = index @model = nil @configuration_hash = nil @template_hashes = nil @idle_vm = nil @current_state = nil @network_reservations = {} @state = job.instance_state(@index) # Expanding virtual states case @state when 'recreate' @recreate = true @state = 'started' when 'restart' @restart = true @state = 'started' end end |
Instance Attribute Details
#configuration_hash ⇒ String
Returns Checksum all of the configuration templates.
17 18 19 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 17 def configuration_hash @configuration_hash end |
#current_state ⇒ Hash
Returns current state as provided by the BOSH Agent.
32 33 34 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 32 def current_state @current_state end |
#idle_vm ⇒ DeploymentPlan::IdleVm (readonly)
Returns Associated resource pool VM.
35 36 37 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 35 def idle_vm @idle_vm end |
#index ⇒ Integer (readonly)
Returns Instance index.
11 12 13 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 11 def index @index end |
#job ⇒ DeploymentPlan::Job (readonly)
Returns Associated job.
8 9 10 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 8 def job @job end |
#model ⇒ Models::Instance (readonly)
Returns Instance model.
14 15 16 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 14 def model @model end |
#network_reservations ⇒ Hash<String, NetworkReservation>
Returns network reservations.
26 27 28 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 26 def network_reservations @network_reservations end |
#recreate ⇒ Boolean
Returns true if this instance needs to be recreated.
38 39 40 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 38 def recreate @recreate end |
#rendered_templates_archive ⇒ Bosh::Director::Core::Templates::RenderedTemplatesArchive
23 24 25 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 23 def rendered_templates_archive @rendered_templates_archive end |
#restart ⇒ Boolean
Returns true if this instance needs to be restarted.
41 42 43 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 41 def restart @restart end |
#state ⇒ String
Returns job state.
29 30 31 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 29 def state @state end |
#template_hashes ⇒ Hash
Returns A hash of template SHA1 hashes.
20 21 22 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 20 def template_hashes @template_hashes end |
Instance Method Details
#add_network_reservation(name, reservation) ⇒ Object
Adds a new network to this instance
130 131 132 133 134 135 136 137 138 139 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 130 def add_network_reservation(name, reservation) old_reservation = @network_reservations[name] if old_reservation raise NetworkReservationAlreadyExists, "`#{self}' already has reservation " + "for network `#{name}', IP #{old_reservation.ip}" end @network_reservations[name] = reservation end |
#allocate_idle_vm ⇒ void
This method returns an undefined value.
Allocates an idle VM in this job resource pool and binds current instance to that idle VM.
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 394 def allocate_idle_vm resource_pool = @job.resource_pool idle_vm = resource_pool.allocate_vm network = resource_pool.network if idle_vm.vm # There's already a resource pool VM that can become our instance, # so we can try to reuse its reservation instance_reservation = @network_reservations[network.name] if instance_reservation instance_reservation.take(idle_vm.network_reservation) end else # VM is not created yet: let's just make it reference this instance # so later it knows what it needs to become idle_vm.bound_instance = self # this also means we no longer need previous VM network reservation # (instance has its own) idle_vm.release_reservation end @idle_vm = idle_vm end |
#bind_model ⇒ void
This method returns an undefined value.
Looks up a DB model for this instance, creates one if doesn’t exist yet.
87 88 89 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 87 def bind_model @model ||= find_or_create_model end |
#bind_unallocated_vm ⇒ void
This method returns an undefined value.
Looks up instance model in DB and binds it to this instance spec. Instance model is created if it’s not found in DB. New idle VM is allocated if instance DB record doesn’t reference one.
95 96 97 98 99 100 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 95 def bind_unallocated_vm bind_model if @model.vm.nil? allocate_idle_vm end end |
#changed? ⇒ Boolean
Returns true if the any of the expected specifications differ from the ones provided by the VM
317 318 319 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 317 def changed? !changes.empty? end |
#changes ⇒ Set<Symbol>
Returns a set of all of the specification differences
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 324 def changes changes = Set.new unless @state == 'detached' && @current_state.nil? changes << :restart if @restart changes << :resource_pool if resource_pool_changed? changes << :network if networks_changed? changes << :packages if packages_changed? changes << :persistent_disk if persistent_disk_changed? changes << :configuration if configuration_changed? changes << :job if job_changed? changes << :state if state_changed? changes << :dns if dns_changed? end changes end |
#configuration_changed? ⇒ Boolean
Returns true if the expected configuration hash differs from the one provided by the VM
254 255 256 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 254 def configuration_changed? configuration_hash != @current_state['configuration_hash'] end |
#disk_currently_attached? ⇒ Boolean
Returns true if the persistent disk is attached to the VM
214 215 216 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 214 def disk_currently_attached? current_state['persistent_disk'].to_i > 0 end |
#disk_size ⇒ Integer
Returns persistent disk size.
184 185 186 187 188 189 190 191 192 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 184 def disk_size if @model.nil? current_state['persistent_disk'].to_i elsif @model.persistent_disk @model.persistent_disk.size else 0 end end |
#dns_changed? ⇒ Boolean
Returns true if the DNS records configured for the instance differ from the ones configured on the DNS server
289 290 291 292 293 294 295 296 297 298 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 289 def dns_changed? if Config.dns_enabled? dns_record_info.any? do |name, ip| Models::Dns::Record.find(:name => name, :type => 'A', :content => ip).nil? end else false end end |
#dns_record_info ⇒ Hash<String, String>
Returns dns record hash of dns name and IP.
196 197 198 199 200 201 202 203 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 196 def dns_record_info dns_record_info = {} network_settings.each do |network_name, network| name = dns_record_name(network_name) dns_record_info[name] = network['ip'] end dns_record_info end |
#dns_record_name(network_name) ⇒ String
Returns dns record name.
207 208 209 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 207 def dns_record_name(network_name) [index, job.canonical_name, canonical(network_name), job.deployment.canonical_name, dns_domain_name].join('.') end |
#find_or_create_model ⇒ Models::Instance
Looks up instance model in DB
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 375 def find_or_create_model if @job.deployment.model.nil? raise DirectorError, 'Deployment model is not bound' end conditions = { deployment_id: @job.deployment.model.id, job: @job.name, index: @index } Models::Instance.find_or_create(conditions) do |model| model.state = 'started' end end |
#job_changed? ⇒ Boolean
Returns true if the expected job configuration differs from the one provided by the VM
261 262 263 264 265 266 267 268 269 270 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 261 def job_changed? job_spec = @job.spec if job_spec != @current_state['job'] # The agent job spec could be in legacy form. job_spec cannot be, # though, because we got it from the spec function in job.rb which # automatically makes it non-legacy. return job_spec != Job.convert_from_legacy_spec(@current_state['job']) end return false end |
#network_settings ⇒ Hash
Returns BOSH network settings used for Agent apply call.
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 155 def network_settings default_properties = {} @job.default_network.each do |key, value| (default_properties[value] ||= []) << key end network_settings = {} @network_reservations.each do |name, reservation| network = @job.deployment.network(name) network_settings[name] = network.network_settings(reservation, default_properties[name]) network_settings[name]['dns_record_name'] = dns_record_name(name) # Somewhat of a hack: for dynamic networks we might know IP address, Netmask & Gateway # if they're featured in agent state, in that case we put them into network spec to satisfy # ConfigurationHasher in both agent and director. if @current_state.is_a?(Hash) && @current_state['networks'].is_a?(Hash) && @current_state['networks'][name].is_a?(Hash) && network_settings[name]['type'] == 'dynamic' %w(ip netmask gateway).each do |key| network_settings[name][key] = @current_state['networks'][name][key] end end end network_settings end |
#networks_changed? ⇒ Boolean
Returns true if the network configuration changed
220 221 222 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 220 def networks_changed? network_settings != @current_state['networks'] end |
#packages_changed? ⇒ Boolean
Returns true if the expected packaged of the running instance differ from the ones provided by the VM
275 276 277 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 275 def packages_changed? @job.package_spec != @current_state['packages'] end |
#persistent_disk_changed? ⇒ Boolean
Returns true if the expected persistent disk differs from the one currently configured on the VM
282 283 284 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 282 def persistent_disk_changed? @job.persistent_disk != disk_size end |
#resource_pool_changed? ⇒ Boolean
Returns true if the expected resource pool differs from the one provided by the VM
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 227 def resource_pool_changed? if @recreate || @job.deployment.recreate return true end if @job.resource_pool.spec != @current_state['resource_pool'] return true end # env is not a part of a resource pool spec but rather gets persisted # in director DB, hence the check below # NOTE: we only update VMs that have env persisted to avoid recreating # everything, so if the director gets updated from the version that # doesn't persist VM env to the version that does, there needs to # be at least one deployment that recreates all VMs before the following # code path gets exercised. if @model && @model.vm && @model.vm.env && @job.resource_pool.env != @model.vm.env return true end false end |
#spec ⇒ Hash<String, Object>
Instance spec that’s passed to the VM during the BOSH Agent apply call. It’s what’s used for comparing the expected vs the actual state.
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 345 def spec spec = { 'deployment' => @job.deployment.name, 'job' => job.spec, 'index' => index, 'networks' => network_settings, 'resource_pool' => job.resource_pool.spec, 'packages' => job.package_spec, 'persistent_disk' => job.persistent_disk, 'configuration_hash' => configuration_hash, 'properties' => job.properties, 'dns_domain_name' => dns_domain_name } if template_hashes spec['template_hashes'] = template_hashes end # Ruby BOSH Agent does not look at 'rendered_templates_archive' # since it renders job templates and then compares template hashes. # Go BOSH Agent has no ability to render ERB so pre-rendered templates are provided. if rendered_templates_archive spec['rendered_templates_archive'] = rendered_templates_archive.spec end spec end |
#state_changed? ⇒ Boolean
Checks if agent view of the instance state is consistent with target instance state.
In case the instance current state is ‘detached’ we should never get to this method call.
308 309 310 311 312 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 308 def state_changed? @state == 'detached' || @state == 'started' && @current_state['job_state'] != 'running' || @state == 'stopped' && @current_state['job_state'] == 'running' end |
#sync_state_with_db ⇒ void
This method returns an undefined value.
Syncs instance state with instance model in DB. This is needed because not all instance states are available in the deployment manifest and we we cannot really persist this data in the agent state (as VM might be stopped or detached).
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 107 def sync_state_with_db if @model.nil? raise DirectorError, "Instance `#{self}' model is not bound" end if @state # Deployment plan explicitly sets state for this instance @model.update(:state => @state) elsif @model.state # Instance has its state persisted from the previous deployment @state = @model.state else # Target instance state should either be persisted in DB or provided # via deployment plan, otherwise something is really wrong raise InstanceTargetStateUndefined, "Instance `#{self}' target state cannot be determined" end end |
#take_network_reservations(reservations) ⇒ void
This method returns an undefined value.
Take any existing valid network reservations
146 147 148 149 150 151 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 146 def take_network_reservations(reservations) reservations.each do |name, provided_reservation| reservation = @network_reservations[name] reservation.take(provided_reservation) if reservation end end |
#to_s ⇒ Object
71 72 73 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 71 def to_s "#{@job.name}/#{@index}" end |
#use_model(model) ⇒ void
This method returns an undefined value.
77 78 79 80 81 82 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 77 def use_model(model) if @model raise DirectorError, 'Instance model is already bound' end @model = model end |