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.
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 405 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
328 329 330 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 328 def changed? !changes.empty? end |
#changes ⇒ Set<Symbol>
Returns a set of all of the specification differences
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 335 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
265 266 267 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 265 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
225 226 227 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 225 def disk_currently_attached? current_state['persistent_disk'].to_i > 0 end |
#disk_size ⇒ Integer
Returns persistent disk size.
195 196 197 198 199 200 201 202 203 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 195 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
300 301 302 303 304 305 306 307 308 309 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 300 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.
207 208 209 210 211 212 213 214 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 207 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.
218 219 220 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 218 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
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 386 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
272 273 274 275 276 277 278 279 280 281 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 272 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 181 182 183 184 185 186 187 188 189 190 191 |
# 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]) # Temporary hack for running errands. # We need to avoid RunErrand task thinking that # network configuration for errand VM differs # from network configuration for its Instance. # # Obviously this does not account for other changes # in network configuration that errand job might need. # (e.g. errand job desires static ip) if @job.starts_on_deploy? network_settings[name]['dns_record_name'] = dns_record_name(name) end # 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
231 232 233 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 231 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
286 287 288 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 286 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
293 294 295 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 293 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
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 238 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.
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 356 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.
319 320 321 322 323 |
# File 'lib/bosh/director/deployment_plan/instance.rb', line 319 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 |