Class: Bosh::Director::ResourcePoolUpdater

Inherits:
Object
  • Object
show all
Defined in:
lib/bosh/director/resource_pool_updater.rb

Instance Method Summary collapse

Constructor Details

#initialize(resource_pool) ⇒ ResourcePoolUpdater

Returns a new instance of ResourcePoolUpdater.



3
4
5
6
7
8
# File 'lib/bosh/director/resource_pool_updater.rb', line 3

def initialize(resource_pool)
  @resource_pool = resource_pool
  @cloud = Config.cloud
  @logger = Config.logger
  @event_log = Config.event_log
end

Instance Method Details

#bound_missing_vm_countObject



202
203
204
205
206
207
208
209
210
# File 'lib/bosh/director/resource_pool_updater.rb', line 202

def bound_missing_vm_count
  counter = 0
  each_idle_vm do |idle_vm|
    next if idle_vm.vm
    next if idle_vm.bound_instance.nil?
    counter += 1
  end
  counter
end

#create_bound_missing_vms(thread_pool) ⇒ Object

Creates missing VMs that have bound instances (as opposed to missing resource pool VMs)



43
44
45
# File 'lib/bosh/director/resource_pool_updater.rb', line 43

def create_bound_missing_vms(thread_pool)
  create_missing_vms(thread_pool) { |idle_vm| !idle_vm.bound_instance.nil? }
end

#create_missing_vm(idle_vm) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/bosh/director/resource_pool_updater.rb', line 47

def create_missing_vm(idle_vm)
  deployment = @resource_pool.deployment_plan.model
  stemcell = @resource_pool.stemcell.model

  vm = VmCreator.new.create(deployment, stemcell, @resource_pool.cloud_properties,
                            idle_vm.network_settings, nil, @resource_pool.env)

  agent = AgentClient.with_defaults(vm.agent_id)
  agent.wait_until_ready

  update_state(agent, vm, idle_vm)

  idle_vm.vm = vm
  idle_vm.current_state = agent.get_state
rescue Exception => e
  @logger.info("Cleaning up the created VM due to an error: #{e}")
  begin
    @cloud.delete_vm(vm.cid) if vm && vm.cid
    vm.destroy if vm && vm.id
  rescue Exception
    @logger.info("Could not cleanup VM: #{vm.cid}") if vm
  end
  raise e
end

#create_missing_vms(thread_pool) {|idle_vm| ... } ⇒ Object

Creates VMs that are considered missing from the deployment

Parameters:

  • thread_pool (ThreadPool)

    Thread pool that will be used to parallelize the operation

Yields:

  • (idle_vm)

    filter for which missing VMs to create



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/bosh/director/resource_pool_updater.rb', line 16

def create_missing_vms(thread_pool)
  counter = 0
  vms_to_process = []

  each_idle_vm do |idle_vm|
    next if idle_vm.vm
    if !block_given? || yield(idle_vm)
      counter += 1
      vms_to_process << idle_vm
    end
  end

  @logger.info("Creating #{counter} missing VMs")
  vms_to_process.each_with_index do |idle_vm, index|
    thread_pool.process do
      @event_log.track("#{@resource_pool.name}/#{index}") do
        with_thread_name("create_missing_vm(#{@resource_pool.name}, #{index}/#{counter})") do
          @logger.info("Creating missing VM")
          create_missing_vm(idle_vm)
        end
      end
    end
  end
end

#delete_extra_vms(thread_pool) ⇒ Object

Deletes extra VMs in a resource pool

Parameters:

  • thread_pool

    Thread pool used to parallelize delete operations



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/bosh/director/resource_pool_updater.rb', line 85

def delete_extra_vms(thread_pool)
  count = extra_vm_count
  @logger.info("Deleting #{count} extra VMs")

  count.times do
    idle_vm = @resource_pool.idle_vms.shift
    vm_cid = idle_vm.vm.cid

    thread_pool.process do
      @event_log.track("#{@resource_pool.name}/#{vm_cid}") do
        @logger.info("Deleting extra VM: #{vm_cid}")
        @cloud.delete_vm(vm_cid)
        idle_vm.vm.destroy
      end
    end
  end
end

#delete_outdated_idle_vms(thread_pool) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/bosh/director/resource_pool_updater.rb', line 103

def delete_outdated_idle_vms(thread_pool)
  count = outdated_idle_vm_count
  index = 0
  index_lock = Mutex.new

  @logger.info("Deleting #{count} outdated idle VMs")

  @resource_pool.idle_vms.each do |idle_vm|
    next unless idle_vm.vm && idle_vm.changed?
    vm_cid = idle_vm.vm.cid

    thread_pool.process do
      @event_log.track("#{@resource_pool.name}/#{vm_cid}") do
        index_lock.synchronize { index += 1 }

        with_thread_name("delete_outdated_vm(#{@resource_pool.name}, #{index - 1}/#{count})") do
          @logger.info("Deleting outdated VM: #{vm_cid}")
          @cloud.delete_vm(vm_cid)
          vm = idle_vm.vm
          idle_vm.clean_vm
          vm.destroy
        end
      end
    end
  end
end

#each_idle_vmObject



165
166
167
168
# File 'lib/bosh/director/resource_pool_updater.rb', line 165

def each_idle_vm
  @resource_pool.allocated_vms.each { |idle_vm| yield idle_vm }
  @resource_pool.idle_vms.each { |idle_vm| yield idle_vm }
end

#each_idle_vm_with_indexObject



170
171
172
173
174
175
176
# File 'lib/bosh/director/resource_pool_updater.rb', line 170

def each_idle_vm_with_index
  index = 0
  each_idle_vm do |idle_vm|
    yield(idle_vm, index)
    index += 1
  end
end

#extra_vm_countObject



178
179
180
181
182
183
# File 'lib/bosh/director/resource_pool_updater.rb', line 178

def extra_vm_count
  @resource_pool.active_vm_count +
      @resource_pool.idle_vms.size +
      @resource_pool.allocated_vms.size -
      @resource_pool.size
end

#generate_agent_idObject



161
162
163
# File 'lib/bosh/director/resource_pool_updater.rb', line 161

def generate_agent_id
  SecureRandom.uuid
end

#missing_vm_countObject



193
194
195
196
197
198
199
200
# File 'lib/bosh/director/resource_pool_updater.rb', line 193

def missing_vm_count
  counter = 0
  each_idle_vm do |idle_vm|
    next if idle_vm.vm
    counter += 1
  end
  counter
end

#outdated_idle_vm_countObject



185
186
187
188
189
190
191
# File 'lib/bosh/director/resource_pool_updater.rb', line 185

def outdated_idle_vm_count
  counter = 0
  @resource_pool.idle_vms.each do |idle_vm|
    counter += 1 if idle_vm.vm && idle_vm.changed?
  end
  counter
end

#reserve_networksObject

Attempts to allocate a dynamic IP address for all idle VMs (unless they already have one). This allows us to fail earlier in case any of resource pools is not big enough to accommodate those VMs.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/bosh/director/resource_pool_updater.rb', line 134

def reserve_networks
  network = @resource_pool.network

  each_idle_vm_with_index do |idle_vm, index|
    unless idle_vm.network_reservation
      reservation = NetworkReservation.new(
          :type => NetworkReservation::DYNAMIC)
      network.reserve(reservation)

      unless reservation.reserved?
        case reservation.error
          when NetworkReservation::CAPACITY
            raise NetworkReservationNotEnoughCapacity,
                  "'#{@resource_pool.name}/#{index}' asked for a dynamic IP " +
                  "but there were no more available"
          else
            raise NetworkReservationError,
                  "'#{@resource_pool.name}/#{index}' failed to reserve " +
                  "dynamic IP: #{reservation.error}"
        end
      end

      idle_vm.network_reservation = reservation
    end
  end
end

#update_state(agent, vm, idle_vm) ⇒ Object



72
73
74
75
76
77
78
79
80
81
# File 'lib/bosh/director/resource_pool_updater.rb', line 72

def update_state(agent, vm, idle_vm)
  state = {
      "deployment" => @resource_pool.deployment_plan.name,
      "resource_pool" => @resource_pool.spec,
      "networks" => idle_vm.network_settings
  }

  vm.update(:apply_spec => state)
  agent.apply(state)
end