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



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

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
129
# 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.vm = nil
          idle_vm.current_state = nil
          vm.destroy
        end
      end
    end
  end
end

#each_idle_vmObject



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

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



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

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



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

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



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

def generate_agent_id
  SecureRandom.uuid
end

#missing_vm_countObject



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

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



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

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.



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
160
# File 'lib/bosh/director/resource_pool_updater.rb', line 135

def reserve_networks
  network = @resource_pool.network

  each_idle_vm do |idle_vm|
    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,
                  "`#{name}/#{index}' asked for a dynamic IP " +
                  "but there were no more available"
          else
            raise NetworkReservationError,
                  "`#{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