vmpooler 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 033cdee6f8934932e9e717b8b229b36541fe2f88
4
- data.tar.gz: d798c6417320e4942bf0965ed3c1e2d303e0bab6
3
+ metadata.gz: a1b32e5280b92e461243bc99e275e1637fe3c644
4
+ data.tar.gz: 702ee61515185102a99cecc1d1475b84f2c19ada
5
5
  SHA512:
6
- metadata.gz: a45de99b68aaf08784fbfac2793a9da60d38c9a8af20ae802362015841e6962dfb2ab027dbfcc7792d8808130752991c3419e95a4ea0764dc625c8a1b97dd5d0
7
- data.tar.gz: 68dbfedba323a249e0a0bace756f2aec21ce1e9a770482b477ea9b197f9ff7a86ba55cdc29a9493756f713c514689f1db66a5196ea01f8f42126315e726f1daa
6
+ metadata.gz: 9566067bbaee8024bdcd05d715082e158a61503de81e9d35a7600ba9567e4f033638350718143c86c17db0e912a1fb42f42032b465350afba666a7f3856c8acb
7
+ data.tar.gz: 415ebd0a8bbbd125ec0a0972be930197f88ac1d927f41683e526aec4465406fe0a6954750892b0b1991b16046686ad64420bb103821620e68e8a017a9b37f208
@@ -1,15 +1,16 @@
1
1
  module Vmpooler
2
2
  require 'date'
3
3
  require 'json'
4
- require 'open-uri'
5
4
  require 'net/ldap'
5
+ require 'open-uri'
6
+ require 'pickup'
6
7
  require 'rbvmomi'
7
8
  require 'redis'
9
+ require 'set'
8
10
  require 'sinatra/base'
9
11
  require 'time'
10
12
  require 'timeout'
11
13
  require 'yaml'
12
- require 'set'
13
14
 
14
15
  %w[api graphite logger pool_manager statsd dummy_statsd generic_connection_pool].each do |lib|
15
16
  require "vmpooler/#{lib}"
@@ -37,15 +37,38 @@ module Vmpooler
37
37
  end
38
38
 
39
39
  def fetch_single_vm(template)
40
- vm = backend.spop('vmpooler__ready__' + template)
41
- return [vm, template] if vm
42
-
40
+ template_backends = [template]
43
41
  aliases = Vmpooler::API.settings.config[:alias]
44
- if aliases && aliased_template = aliases[template]
45
- vm = backend.spop('vmpooler__ready__' + aliased_template)
46
- return [vm, aliased_template] if vm
42
+ if aliases
43
+ template_backends << aliases[template] if aliases[template]
44
+
45
+ pool_index = pool_index(pools)
46
+ weighted_pools = {}
47
+ template_backends.each do |t|
48
+ next unless pool_index.key? t
49
+ index = pool_index[t]
50
+ clone_target = pools[index]['clone_target'] || config['clone_target']
51
+ next unless config.key?('backend_weight')
52
+ weight = config['backend_weight'][clone_target]
53
+ if weight
54
+ weighted_pools[t] = weight
55
+ end
56
+ end
57
+
58
+ if weighted_pools.count == template_backends.count
59
+ pickup = Pickup.new(weighted_pools)
60
+ selection = pickup.pick
61
+ template_backends.delete(selection)
62
+ template_backends.unshift(selection)
63
+ else
64
+ template_backends = template_backends.sample(template_backends.count)
65
+ end
47
66
  end
48
67
 
68
+ template_backends.each do |t|
69
+ vm = backend.spop('vmpooler__ready__' + t)
70
+ return [vm, t] if vm
71
+ end
49
72
  [nil, nil]
50
73
  end
51
74
 
@@ -188,8 +188,10 @@ module Vmpooler
188
188
 
189
189
  # Check if the hostname has magically changed from underneath Pooler
190
190
  vm_hash = provider.get_vm(pool['name'], vm)
191
+ return unless vm_hash.is_a? Hash
191
192
  hostname = vm_hash['hostname']
192
193
 
194
+ return if hostname.nil?
193
195
  return if hostname.empty?
194
196
  return if hostname == vm
195
197
  $redis.smove('vmpooler__ready__' + pool['name'], 'vmpooler__completed__' + pool['name'], vm)
@@ -243,20 +245,18 @@ module Vmpooler
243
245
  end
244
246
 
245
247
  # Clone a VM
246
- def clone_vm(pool, provider)
248
+ def clone_vm(pool_name, provider)
247
249
  Thread.new do
248
250
  begin
249
- _clone_vm(pool, provider)
251
+ _clone_vm(pool_name, provider)
250
252
  rescue => err
251
- $logger.log('s', "[!] [#{pool['name']}] failed while cloning VM with an error: #{err}")
253
+ $logger.log('s', "[!] [#{pool_name}] failed while cloning VM with an error: #{err}")
252
254
  raise
253
255
  end
254
256
  end
255
257
  end
256
258
 
257
- def _clone_vm(pool, provider)
258
- pool_name = pool['name']
259
-
259
+ def _clone_vm(pool_name, provider)
260
260
  # Generate a randomized hostname
261
261
  o = [('a'..'z'), ('0'..'9')].map(&:to_a).flatten
262
262
  new_vmname = $config[:config]['prefix'] + o[rand(25)] + (0...14).map { o[rand(o.length)] }.join
@@ -723,7 +723,16 @@ module Vmpooler
723
723
  end
724
724
 
725
725
  def prepare_template(pool, provider)
726
- provider.create_template_delta_disks(pool) if $config[:config]['create_template_delta_disks']
726
+ if $config[:config]['create_template_delta_disks']
727
+ unless $redis.sismember('vmpooler__template__deltas', pool['template'])
728
+ begin
729
+ provider.create_template_delta_disks(pool)
730
+ $redis.sadd('vmpooler__template__deltas', pool['template'])
731
+ rescue => err
732
+ $logger.log('s', "[!] [#{pool['name']}] failed while preparing a template with an error. As a result vmpooler could not create the template delta disks. Either a template delta disk already exists, or the template delta disk creation failed. The error is: #{err}")
733
+ end
734
+ end
735
+ end
727
736
  $redis.hset('vmpooler__template__prepared', pool['name'], pool['template'])
728
737
  end
729
738
 
@@ -779,7 +788,9 @@ module Vmpooler
779
788
  $logger.log('s', "[*] [#{pool['name']}] is ready for use")
780
789
  end
781
790
 
782
- def remove_excess_vms(pool, provider, ready, total)
791
+ def remove_excess_vms(pool)
792
+ ready = $redis.scard("vmpooler__ready__#{pool['name']}")
793
+ total = $redis.scard("vmpooler__pending__#{pool['name']}") + ready
783
794
  return if total.nil?
784
795
  return if total == 0
785
796
  mutex = pool_mutex(pool['name'])
@@ -811,17 +822,7 @@ module Vmpooler
811
822
  end
812
823
  end
813
824
 
814
- def _check_pool(pool, provider)
815
- pool_check_response = {
816
- discovered_vms: 0,
817
- checked_running_vms: 0,
818
- checked_ready_vms: 0,
819
- checked_pending_vms: 0,
820
- destroyed_vms: 0,
821
- migrated_vms: 0,
822
- cloned_vms: 0
823
- }
824
- # INVENTORY
825
+ def create_inventory(pool, provider, pool_check_response)
825
826
  inventory = {}
826
827
  begin
827
828
  mutex = pool_mutex(pool['name'])
@@ -844,103 +845,170 @@ module Vmpooler
844
845
  end
845
846
  end
846
847
  rescue => err
847
- $logger.log('s', "[!] [#{pool['name']}] _check_pool failed with an error while inspecting inventory: #{err}")
848
- return pool_check_response
848
+ $logger.log('s', "[!] [#{pool['name']}] _check_pool failed with an error while running create_inventory: #{err}")
849
+ raise(err)
849
850
  end
851
+ inventory
852
+ end
850
853
 
851
- # RUNNING
852
- $redis.smembers("vmpooler__running__#{pool['name']}").each do |vm|
854
+ def check_running_pool_vms(pool_name, provider, pool_check_response, inventory)
855
+ $redis.smembers("vmpooler__running__#{pool_name}").each do |vm|
853
856
  if inventory[vm]
854
857
  begin
855
858
  vm_lifetime = $redis.hget('vmpooler__vm__' + vm, 'lifetime') || $config[:config]['vm_lifetime'] || 12
856
859
  pool_check_response[:checked_running_vms] += 1
857
- check_running_vm(vm, pool['name'], vm_lifetime, provider)
860
+ check_running_vm(vm, pool_name, vm_lifetime, provider)
858
861
  rescue => err
859
- $logger.log('d', "[!] [#{pool['name']}] _check_pool with an error while evaluating running VMs: #{err}")
862
+ $logger.log('d', "[!] [#{pool_name}] _check_pool with an error while evaluating running VMs: #{err}")
860
863
  end
861
864
  else
862
- move_vm_queue(pool['name'], vm, 'running', 'completed', 'is a running VM but is missing from inventory. Marking as completed.')
865
+ move_vm_queue(pool_name, vm, 'running', 'completed', 'is a running VM but is missing from inventory. Marking as completed.')
863
866
  end
864
867
  end
868
+ end
865
869
 
866
- # READY
867
- $redis.smembers("vmpooler__ready__#{pool['name']}").each do |vm|
870
+ def check_ready_pool_vms(pool_name, provider, pool_check_response, inventory, pool_ttl = 0)
871
+ $redis.smembers("vmpooler__ready__#{pool_name}").each do |vm|
868
872
  if inventory[vm]
869
873
  begin
870
874
  pool_check_response[:checked_ready_vms] += 1
871
- check_ready_vm(vm, pool, pool['ready_ttl'] || 0, provider)
875
+ check_ready_vm(vm, pool_name, pool_ttl || 0, provider)
872
876
  rescue => err
873
- $logger.log('d', "[!] [#{pool['name']}] _check_pool failed with an error while evaluating ready VMs: #{err}")
877
+ $logger.log('d', "[!] [#{pool_name}] _check_pool failed with an error while evaluating ready VMs: #{err}")
874
878
  end
875
879
  else
876
- move_vm_queue(pool['name'], vm, 'ready', 'completed', 'is a ready VM but is missing from inventory. Marking as completed.')
880
+ move_vm_queue(pool_name, vm, 'ready', 'completed', 'is a ready VM but is missing from inventory. Marking as completed.')
877
881
  end
878
882
  end
883
+ end
879
884
 
880
- # PENDING
881
- $redis.smembers("vmpooler__pending__#{pool['name']}").each do |vm|
882
- pool_timeout = pool['timeout'] || $config[:config]['timeout'] || 15
885
+ def check_pending_pool_vms(pool_name, provider, pool_check_response, inventory, pool_timeout = nil)
886
+ pool_timeout ||= $config[:config]['timeout'] || 15
887
+ $redis.smembers("vmpooler__pending__#{pool_name}").each do |vm|
883
888
  if inventory[vm]
884
889
  begin
885
890
  pool_check_response[:checked_pending_vms] += 1
886
- check_pending_vm(vm, pool['name'], pool_timeout, provider)
891
+ check_pending_vm(vm, pool_name, pool_timeout, provider)
887
892
  rescue => err
888
- $logger.log('d', "[!] [#{pool['name']}] _check_pool failed with an error while evaluating pending VMs: #{err}")
893
+ $logger.log('d', "[!] [#{pool_name}] _check_pool failed with an error while evaluating pending VMs: #{err}")
889
894
  end
890
895
  else
891
- fail_pending_vm(vm, pool['name'], pool_timeout, false)
896
+ fail_pending_vm(vm, pool_name, pool_timeout, false)
892
897
  end
893
898
  end
899
+ end
894
900
 
895
- # COMPLETED
896
- $redis.smembers("vmpooler__completed__#{pool['name']}").each do |vm|
901
+ def check_completed_pool_vms(pool_name, provider, pool_check_response, inventory)
902
+ $redis.smembers("vmpooler__completed__#{pool_name}").each do |vm|
897
903
  if inventory[vm]
898
904
  begin
899
905
  pool_check_response[:destroyed_vms] += 1
900
- destroy_vm(vm, pool['name'], provider)
906
+ destroy_vm(vm, pool_name, provider)
901
907
  rescue => err
902
- $redis.srem("vmpooler__completed__#{pool['name']}", vm)
903
- $redis.hdel("vmpooler__active__#{pool['name']}", vm)
908
+ $redis.srem("vmpooler__completed__#{pool_name}", vm)
909
+ $redis.hdel("vmpooler__active__#{pool_name}", vm)
904
910
  $redis.del("vmpooler__vm__#{vm}")
905
- $logger.log('d', "[!] [#{pool['name']}] _check_pool failed with an error while evaluating completed VMs: #{err}")
911
+ $logger.log('d', "[!] [#{pool_name}] _check_pool failed with an error while evaluating completed VMs: #{err}")
906
912
  end
907
913
  else
908
- $logger.log('s', "[!] [#{pool['name']}] '#{vm}' not found in inventory, removed from 'completed' queue")
909
- $redis.srem("vmpooler__completed__#{pool['name']}", vm)
910
- $redis.hdel("vmpooler__active__#{pool['name']}", vm)
914
+ $logger.log('s', "[!] [#{pool_name}] '#{vm}' not found in inventory, removed from 'completed' queue")
915
+ $redis.srem("vmpooler__completed__#{pool_name}", vm)
916
+ $redis.hdel("vmpooler__active__#{pool_name}", vm)
911
917
  $redis.del("vmpooler__vm__#{vm}")
912
918
  end
913
919
  end
920
+ end
914
921
 
915
- # DISCOVERED
922
+ def check_discovered_pool_vms(pool_name)
916
923
  begin
917
- $redis.smembers("vmpooler__discovered__#{pool['name']}").each do |vm|
924
+ $redis.smembers("vmpooler__discovered__#{pool_name}").each do |vm|
918
925
  %w[pending ready running completed].each do |queue|
919
- if $redis.sismember("vmpooler__#{queue}__#{pool['name']}", vm)
920
- $logger.log('d', "[!] [#{pool['name']}] '#{vm}' found in '#{queue}', removed from 'discovered' queue")
921
- $redis.srem("vmpooler__discovered__#{pool['name']}", vm)
926
+ if $redis.sismember("vmpooler__#{queue}__#{pool_name}", vm)
927
+ $logger.log('d', "[!] [#{pool_name}] '#{vm}' found in '#{queue}', removed from 'discovered' queue")
928
+ $redis.srem("vmpooler__discovered__#{pool_name}", vm)
922
929
  end
923
930
  end
924
931
 
925
- if $redis.sismember("vmpooler__discovered__#{pool['name']}", vm)
926
- $redis.smove("vmpooler__discovered__#{pool['name']}", "vmpooler__completed__#{pool['name']}", vm)
932
+ if $redis.sismember("vmpooler__discovered__#{pool_name}", vm)
933
+ $redis.smove("vmpooler__discovered__#{pool_name}", "vmpooler__completed__#{pool_name}", vm)
927
934
  end
928
935
  end
929
936
  rescue => err
930
- $logger.log('d', "[!] [#{pool['name']}] _check_pool failed with an error while evaluating discovered VMs: #{err}")
937
+ $logger.log('d', "[!] [#{pool_name}] _check_pool failed with an error while evaluating discovered VMs: #{err}")
931
938
  end
939
+ end
932
940
 
933
- # MIGRATIONS
934
- $redis.smembers("vmpooler__migrating__#{pool['name']}").each do |vm|
941
+ def check_migrating_pool_vms(pool_name, provider, pool_check_response, inventory)
942
+ $redis.smembers("vmpooler__migrating__#{pool_name}").each do |vm|
935
943
  if inventory[vm]
936
944
  begin
937
945
  pool_check_response[:migrated_vms] += 1
938
- migrate_vm(vm, pool['name'], provider)
946
+ migrate_vm(vm, pool_name, provider)
947
+ rescue => err
948
+ $logger.log('s', "[x] [#{pool_name}] '#{vm}' failed to migrate: #{err}")
949
+ end
950
+ end
951
+ end
952
+ end
953
+
954
+ def repopulate_pool_vms(pool_name, provider, pool_check_response, pool_size)
955
+ return if pool_mutex(pool_name).locked?
956
+ ready = $redis.scard("vmpooler__ready__#{pool_name}")
957
+ total = $redis.scard("vmpooler__pending__#{pool_name}") + ready
958
+
959
+ $metrics.gauge("ready.#{pool_name}", $redis.scard("vmpooler__ready__#{pool_name}"))
960
+ $metrics.gauge("running.#{pool_name}", $redis.scard("vmpooler__running__#{pool_name}"))
961
+
962
+ if $redis.get("vmpooler__empty__#{pool_name}")
963
+ $redis.del("vmpooler__empty__#{pool_name}") unless ready.zero?
964
+ elsif ready.zero?
965
+ $redis.set("vmpooler__empty__#{pool_name}", 'true')
966
+ $logger.log('s', "[!] [#{pool_name}] is empty")
967
+ end
968
+
969
+ (pool_size - total).times do
970
+ if $redis.get('vmpooler__tasks__clone').to_i < $config[:config]['task_limit'].to_i
971
+ begin
972
+ $redis.incr('vmpooler__tasks__clone')
973
+ pool_check_response[:cloned_vms] += 1
974
+ clone_vm(pool_name, provider)
939
975
  rescue => err
940
- $logger.log('s', "[x] [#{pool['name']}] '#{vm}' failed to migrate: #{err}")
976
+ $logger.log('s', "[!] [#{pool_name}] clone failed during check_pool with an error: #{err}")
977
+ $redis.decr('vmpooler__tasks__clone')
978
+ raise
941
979
  end
942
980
  end
943
981
  end
982
+ end
983
+
984
+ def _check_pool(pool, provider)
985
+ pool_check_response = {
986
+ discovered_vms: 0,
987
+ checked_running_vms: 0,
988
+ checked_ready_vms: 0,
989
+ checked_pending_vms: 0,
990
+ destroyed_vms: 0,
991
+ migrated_vms: 0,
992
+ cloned_vms: 0
993
+ }
994
+
995
+ begin
996
+ inventory = create_inventory(pool, provider, pool_check_response)
997
+ rescue => err
998
+ return(pool_check_response)
999
+ end
1000
+
1001
+ check_running_pool_vms(pool['name'], provider, pool_check_response, inventory)
1002
+
1003
+ check_ready_pool_vms(pool['name'], provider, pool_check_response, inventory, pool['ready_ttl'])
1004
+
1005
+ check_pending_pool_vms(pool['name'], provider, pool_check_response, inventory, pool['timeout'])
1006
+
1007
+ check_completed_pool_vms(pool['name'], provider, pool_check_response, inventory)
1008
+
1009
+ check_discovered_pool_vms(pool['name'])
1010
+
1011
+ check_migrating_pool_vms(pool['name'], provider, pool_check_response, inventory)
944
1012
 
945
1013
  # UPDATE TEMPLATE
946
1014
  # Evaluates a pool template to ensure templates are prepared adequately for the configured provider
@@ -948,46 +1016,15 @@ module Vmpooler
948
1016
  # Additionally, a pool will drain ready and pending instances
949
1017
  evaluate_template(pool, provider)
950
1018
 
951
- # REPOPULATE
952
- # Do not attempt to repopulate a pool while a template is updating
953
- unless pool_mutex(pool['name']).locked?
954
- ready = $redis.scard("vmpooler__ready__#{pool['name']}")
955
- total = $redis.scard("vmpooler__pending__#{pool['name']}") + ready
1019
+ # Check to see if a pool size change has been made via the configuration API
1020
+ # Since check_pool runs in a loop it does not
1021
+ # otherwise identify this change when running
1022
+ update_pool_size(pool)
956
1023
 
957
- $metrics.gauge("ready.#{pool['name']}", $redis.scard("vmpooler__ready__#{pool['name']}"))
958
- $metrics.gauge("running.#{pool['name']}", $redis.scard("vmpooler__running__#{pool['name']}"))
959
-
960
- if $redis.get("vmpooler__empty__#{pool['name']}")
961
- $redis.del("vmpooler__empty__#{pool['name']}") unless ready.zero?
962
- elsif ready.zero?
963
- $redis.set("vmpooler__empty__#{pool['name']}", 'true')
964
- $logger.log('s', "[!] [#{pool['name']}] is empty")
965
- end
966
-
967
- # Check to see if a pool size change has been made via the configuration API
968
- # Since check_pool runs in a loop it does not
969
- # otherwise identify this change when running
970
- update_pool_size(pool)
971
-
972
- if total < pool['size']
973
- (1..(pool['size'] - total)).each do |_i|
974
- if $redis.get('vmpooler__tasks__clone').to_i < $config[:config]['task_limit'].to_i
975
- begin
976
- $redis.incr('vmpooler__tasks__clone')
977
- pool_check_response[:cloned_vms] += 1
978
- clone_vm(pool, provider)
979
- rescue => err
980
- $logger.log('s', "[!] [#{pool['name']}] clone failed during check_pool with an error: #{err}")
981
- $redis.decr('vmpooler__tasks__clone')
982
- raise
983
- end
984
- end
985
- end
986
- end
987
- end
1024
+ repopulate_pool_vms(pool['name'], provider, pool_check_response, pool['size'])
988
1025
 
989
1026
  # Remove VMs in excess of the configured pool size
990
- remove_excess_vms(pool, provider, ready, total)
1027
+ remove_excess_vms(pool)
991
1028
 
992
1029
  pool_check_response
993
1030
  end
@@ -428,7 +428,7 @@ module Vmpooler
428
428
 
429
429
  def vm_ready?(_pool_name, vm_name)
430
430
  begin
431
- open_socket(vm_name)
431
+ open_socket(vm_name, global_config[:config]['domain'])
432
432
  rescue => _err
433
433
  return false
434
434
  end
@@ -1,3 +1,3 @@
1
1
  module Vmpooler
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.2.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vmpooler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-24 00:00:00.000000000 Z
11
+ date: 2018-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pickup
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.11
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.11
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: puma
15
29
  requirement: !ruby/object:Gem::Requirement