Class: Bosh::Director::DeploymentPlan::Job

Inherits:
Object
  • Object
show all
Includes:
Template::PropertyHelper
Defined in:
lib/bosh/director/deployment_plan/job.rb

Constant Summary collapse

VALID_LIFECYCLE_PROFILES =
%w(service errand)
DEFAULT_LIFECYCLE_PROFILE =
'service'
VALID_JOB_STATES =

started, stopped and detached are real states (persisting in DB and reflecting target instance state) recreate and restart are two virtual states (both set target instance state to “started” and set appropriate instance spec modifiers)

%w(started stopped detached recreate restart)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(deployment) ⇒ Job



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/bosh/director/deployment_plan/job.rb', line 83

def initialize(deployment)
  @deployment = deployment

  @release = nil
  @templates = []
  @all_properties = nil # All properties available to job
  @properties = nil # Actual job properties

  @instances = []
  @unneeded_instances = []
  @instance_states = {}

  @packages = {}
end

Instance Attribute Details

#all_propertiesObject

Returns the value of attribute all_properties.



70
71
72
# File 'lib/bosh/director/deployment_plan/job.rb', line 70

def all_properties
  @all_properties
end

#canonical_nameString



26
27
28
# File 'lib/bosh/director/deployment_plan/job.rb', line 26

def canonical_name
  @canonical_name
end

#default_networkDeploymentPlan::Network



42
43
44
# File 'lib/bosh/director/deployment_plan/job.rb', line 42

def default_network
  @default_network
end

#deploymentDeploymentPlan



32
33
34
# File 'lib/bosh/director/deployment_plan/job.rb', line 32

def deployment
  @deployment
end

#instance_statesHash<Integer, String>



68
69
70
# File 'lib/bosh/director/deployment_plan/job.rb', line 68

def instance_states
  @instance_states
end

#instancesArray<DeploymentPlan::Instance>



58
59
60
# File 'lib/bosh/director/deployment_plan/job.rb', line 58

def instances
  @instances
end

#lifecycleString



23
24
25
# File 'lib/bosh/director/deployment_plan/job.rb', line 23

def lifecycle
  @lifecycle
end

#nameString



20
21
22
# File 'lib/bosh/director/deployment_plan/job.rb', line 20

def name
  @name
end

#packagesHash<String, DeploymentPlan::Package] Packages included into this job



52
53
54
# File 'lib/bosh/director/deployment_plan/job.rb', line 52

def packages
  @packages
end

#persistent_disk_poolDiskPool



29
30
31
# File 'lib/bosh/director/deployment_plan/job.rb', line 29

def persistent_disk_pool
  @persistent_disk_pool
end

#propertiesHash



48
49
50
# File 'lib/bosh/director/deployment_plan/job.rb', line 48

def properties
  @properties
end

#releaseDeploymentPlan::ReleaseVersion



35
36
37
# File 'lib/bosh/director/deployment_plan/job.rb', line 35

def release
  @release
end

#resource_poolDeploymentPlan::ResourcePool



39
40
41
# File 'lib/bosh/director/deployment_plan/job.rb', line 39

def resource_pool
  @resource_pool
end

#stateString



65
66
67
# File 'lib/bosh/director/deployment_plan/job.rb', line 65

def state
  @state
end

#templatesArray<DeploymentPlan::Template] Templates included into the job



45
46
47
# File 'lib/bosh/director/deployment_plan/job.rb', line 45

def templates
  @templates
end

#unneeded_instancesArray<Models::Instance>



62
63
64
# File 'lib/bosh/director/deployment_plan/job.rb', line 62

def unneeded_instances
  @unneeded_instances
end

#updateDeploymentPlan::UpdateConfig



55
56
57
# File 'lib/bosh/director/deployment_plan/job.rb', line 55

def update
  @update
end

Class Method Details

.convert_from_legacy_spec(job_spec) ⇒ Object

Takes in a job spec and returns a job spec in the new format, if it needs to be modified. The new format has “templates” key, which is an array with each template’s data. This is used for job collocation, specifically for the agent’s current job spec when compared to the director’s. We only convert their template to a single array entry because it should be impossible for the agent to have a job spec with multiple templates in legacy form.



109
110
111
112
113
114
115
116
117
118
# File 'lib/bosh/director/deployment_plan/job.rb', line 109

def self.convert_from_legacy_spec(job_spec)
  return job_spec if !self.is_legacy_spec?(job_spec)
  template = {
    "name" => job_spec["template"],
    "version" => job_spec["version"],
    "sha1" => job_spec["sha1"],
    "blobstore_id" => job_spec["blobstore_id"]
  }
  job_spec["templates"] = [template]
end

.is_legacy_spec?(job_spec) ⇒ Boolean



98
99
100
# File 'lib/bosh/director/deployment_plan/job.rb', line 98

def self.is_legacy_spec?(job_spec)
  !job_spec.has_key?("templates")
end

.parse(deployment, job_spec, event_log, logger) ⇒ Bosh::Director::DeploymentPlan::Job



77
78
79
80
# File 'lib/bosh/director/deployment_plan/job.rb', line 77

def self.parse(deployment, job_spec, event_log, logger)
  parser = JobSpecParser.new(deployment, event_log, logger)
  parser.parse(job_spec)
end

Instance Method Details

#bind_instance_networksObject



233
234
235
236
237
238
239
240
241
242
243
# File 'lib/bosh/director/deployment_plan/job.rb', line 233

def bind_instance_networks
  instances.each do |instance|
    instance.network_reservations.each do |net_name, reservation|
      unless reservation.reserved?
        network = @deployment.network(net_name)
        network.reserve!(reservation, "`#{name}/#{instance.index}'")
        instance.vm.use_reservation(reservation) if instance.vm
      end
    end
  end
end

#bind_propertiesObject

Extracts only the properties needed by this job. This is decoupled from parsing properties because templates need to be bound to their models before ‘bind_properties’ is being called (as we persist job template property definitions in DB).



193
194
195
# File 'lib/bosh/director/deployment_plan/job.rb', line 193

def bind_properties
  @properties = filter_properties(@all_properties)
end

#bind_unallocated_vmsObject



223
224
225
226
227
228
229
230
231
# File 'lib/bosh/director/deployment_plan/job.rb', line 223

def bind_unallocated_vms
  instances.each do |instance|
    instance.bind_unallocated_vm

    # Now that we know every VM has been allocated and
    # instance models are bound, we can sync the state.
    instance.sync_state_with_db
  end
end

#can_run_as_errand?Boolean



249
250
251
# File 'lib/bosh/director/deployment_plan/job.rb', line 249

def can_run_as_errand?
  @lifecycle == 'errand'
end

#instance(index) ⇒ DeploymentPlan::Instance

Returns job instance by index



170
171
172
# File 'lib/bosh/director/deployment_plan/job.rb', line 170

def instance(index)
  @instances[index]
end

#instance_state(index) ⇒ String?

Returns the state state of job instance by its index



177
178
179
# File 'lib/bosh/director/deployment_plan/job.rb', line 177

def instance_state(index)
  @instance_states[index] || @state
end

#package_specHash<String, Hash>

Returns package specs for all packages in the job indexed by package name. To be used by all instances of the job to populate agent state.



158
159
160
161
162
163
164
165
# File 'lib/bosh/director/deployment_plan/job.rb', line 158

def package_spec
  result = {}
  @packages.each do |name, package|
    result[name] = package.spec
  end

  result.select { |name, _| run_time_dependencies.include? name }
end

#persistent_disk=(disk_size) ⇒ Object

reverse compatibility: translate disk size into a disk pool



254
255
256
257
258
# File 'lib/bosh/director/deployment_plan/job.rb', line 254

def persistent_disk=(disk_size)
  disk_pool = DiskPool.new(SecureRandom.uuid)
  disk_pool.disk_size = disk_size
  @persistent_disk_pool = disk_pool
end

#specHash

Returns job spec as a Hash. To be used by all instances of the job to populate agent state.



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/bosh/director/deployment_plan/job.rb', line 123

def spec
  first_template = @templates[0]
  result = {
    "name" => @name,
    "templates" => [],
    # --- Legacy ---
    "template" => first_template.name,
    "version" => first_template.version,
    "sha1" => first_template.sha1,
    "blobstore_id" => first_template.blobstore_id
  }
  if first_template.logs
    result["logs"] = first_template.logs
  end
  # --- /Legacy ---

  @templates.each do |template|
    template_entry = {
      "name" => template.name,
      "version" => template.version,
      "sha1" => template.sha1,
      "blobstore_id" => template.blobstore_id
    }
    if template.logs
      template_entry["logs"] = template.logs
    end
    result["templates"] << template_entry
  end

  result
end

#starts_on_deploy?Boolean



245
246
247
# File 'lib/bosh/director/deployment_plan/job.rb', line 245

def starts_on_deploy?
  @lifecycle == 'service'
end

#use_compiled_package(compiled_package_model) ⇒ void

This method returns an undefined value.

Registers compiled package with this job.



184
185
186
187
# File 'lib/bosh/director/deployment_plan/job.rb', line 184

def use_compiled_package(compiled_package_model)
  compiled_package = CompiledPackage.new(compiled_package_model)
  @packages[compiled_package.name] = compiled_package
end

#validate_package_names_do_not_collide!Object



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/bosh/director/deployment_plan/job.rb', line 197

def validate_package_names_do_not_collide!
  releases_by_package_names = templates
    .reduce([]) { |memo, t| memo + t.model.package_names.product([t.release]) }
    .reduce({}) { |memo, package_name_and_release_version|
      package_name = package_name_and_release_version.first
      release_version = package_name_and_release_version.last
      memo[package_name] ||= Set.new
      memo[package_name] << release_version
      memo
    }

  releases_by_package_names.each do |package_name, releases|
    if releases.size > 1
      release1, release2 = releases.to_a[0..1]
      offending_template1 = templates.find { |t| t.release == release1 }
      offending_template2 = templates.find { |t| t.release == release2 }

      raise JobPackageCollision,
            "Package name collision detected in job `#{@name}': "\
            "template `#{release1.name}/#{offending_template1.name}' depends on package `#{release1.name}/#{package_name}', "\
            "template `#{release2.name}/#{offending_template2.name}' depends on `#{release2.name}/#{package_name}'. " +
            'BOSH cannot currently collocate two packages with identical names from separate releases.'
    end
  end
end