kameleon-builder 2.2.3 → 2.2.4

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.
Files changed (37) hide show
  1. data/CHANGELOG.rst +13 -0
  2. data/contrib/kameleon_bashrc.sh +6 -6
  3. data/lib/kameleon/engine.rb +5 -2
  4. data/lib/kameleon/persistent_cache.rb +43 -25
  5. data/lib/kameleon/recipe.rb +12 -7
  6. data/lib/kameleon/step.rb +2 -0
  7. data/templates/qemu/centos6.5-x86_64.yaml +18 -9
  8. data/templates/qemu/centos7-x86_64.yaml +4 -1
  9. data/templates/qemu/fedora20-x86_64.yaml +4 -1
  10. data/templates/steps/bootstrap/centos/6.5/yum_bootstrap.yaml +65 -0
  11. data/templates/steps/bootstrap/start_qemu.yaml +4 -2
  12. data/templates/steps/bootstrap/start_virtualbox.yaml +3 -2
  13. data/templates/steps/bootstrap/switch_context_qemu.yaml +5 -4
  14. data/templates/steps/bootstrap/switch_context_virtualbox.yaml +4 -3
  15. data/templates/steps/export/save_appliance_from_g5k.yaml +1 -1
  16. data/templates/steps/export/vagrant_save_appliance.yaml +7 -0
  17. data/templates/steps/export/virtualbox_save_appliance.yaml +0 -6
  18. data/templates/steps/setup/centos/6.5/configure_repo.yaml +9 -0
  19. data/templates/steps/setup/centos/6.5/configure_system.yaml +19 -0
  20. data/templates/steps/setup/centos/6.5/minimal_install.yaml +3 -0
  21. data/templates/steps/setup/centos/6.5/setup_vagrant_box.yaml +76 -0
  22. data/templates/steps/setup/debian/setup_vagrant_box.yaml +6 -8
  23. data/templates/steps/setup/fedora/configure_system.yaml +18 -0
  24. data/templates/steps/setup/fedora/install_bootloader.yaml +1 -6
  25. data/templates/steps/setup/fedora/update_system.yaml +1 -1
  26. data/templates/virtualbox/archlinux-x86_64.yaml +0 -1
  27. data/templates/virtualbox/centos6.5-vagrant-x86_64.yaml +33 -0
  28. data/templates/virtualbox/centos6.5-x86_64.yaml +20 -10
  29. data/templates/virtualbox/centos7-x86_64.yaml +4 -2
  30. data/templates/virtualbox/debian7-amd64.yaml +11 -13
  31. data/templates/virtualbox/debian7-vagrant-amd64.yaml +32 -0
  32. data/templates/virtualbox/fedora20-x86_64.yaml +4 -2
  33. data/templates/virtualbox/ubuntu-12.04-amd64.yaml +2 -2
  34. data/version.txt +1 -1
  35. metadata +26 -12
  36. checksums.yaml +0 -7
  37. data/templates/vagrant/debian7-amd64.yaml +0 -130
@@ -1,6 +1,19 @@
1
1
  Kameleon CHANGELOG
2
2
  ==================
3
3
 
4
+ version 2.2.4
5
+ -------------
6
+ Released on Sep 2nd 2014
7
+
8
+ - [template] Added the ``-cpu host`` option to qemu to improve performances
9
+ - [template] Made centos image as close as possible as default Centos installation
10
+ - [template] Configured SELinux for Fedora and Centos
11
+ - [template] Fixed Grid'5000 export step
12
+ - [template] Extended vagrant recipes from virtualbox recipes
13
+ - [core] Adding the step elapsed time to the Kamelon output
14
+ - [proxy cache] Restructured persistent cache and improved caching of pipes
15
+ - [proxy cache] Added ``ProxyAdrres`` paramter to polipo to take into account all the host network interfaces
16
+
4
17
  version 2.2.3
5
18
  -------------
6
19
  Released on Aug 19th 2014
@@ -139,14 +139,14 @@ fi
139
139
 
140
140
  function __download {
141
141
  echo "Downloading: $1..."
142
- if which curl >/dev/null; then
143
- curl -# -L --retry 999 --retry-max-time 0 "$1" -o "$2" 2>&1
142
+ if which wget >/dev/null; then
143
+ wget --progress=bar:force "$1" -O "$2" 2>&1
144
144
  else
145
- fail "curl is missing, trying with wget..."
146
- if which wget >/dev/null; then
147
- wget --progress=bar:force "$1" -O "$2" 2>&1
145
+ fail "wget is missing, trying with curl..."
146
+ if which curl >/dev/null; then
147
+ curl -# -L --retry 999 --retry-max-time 0 "$1" -o "$2" 2>&1
148
148
  else
149
- fail "wget is missing, trying with python..."
149
+ fail "curl is missing, trying with python..."
150
150
  if which python >/dev/null; then
151
151
  python -c "
152
152
  import sys
@@ -1,6 +1,7 @@
1
1
  require 'kameleon/recipe'
2
2
  require 'kameleon/context'
3
3
  require 'kameleon/persistent_cache'
4
+ # require 'pry'
4
5
  module Kameleon
5
6
 
6
7
  class Engine
@@ -38,7 +39,7 @@ module Kameleon
38
39
  @cache.name = @recipe.name
39
40
  @cache.mode = @options[:cache] ? :build : :from
40
41
  @cache.cache_path = @options[:from_cache]
41
- @cache.recipe_files = @recipe.files # I'm passing the Pathname objects
42
+ @cache.recipe_files = @recipe.files + @recipe.base_recipes_files# I'm passing the Pathname objects
42
43
  @cache.recipe_path = @recipe.path
43
44
 
44
45
  if @recipe.global["in_context"]["proxy_cache"].nil? then
@@ -151,6 +152,7 @@ module Kameleon
151
152
  def do_steps(section_name)
152
153
  section = @recipe.sections.fetch(section_name)
153
154
  section.sequence do |macrostep|
155
+ macrostep_time = Time.now.to_i
154
156
  if @cache then
155
157
  Kameleon.ui.info("Starting proxy cache server for macrostep '#{macrostep.name}'...")
156
158
  # the following function start a polipo web proxy and stops a previous run
@@ -186,6 +188,7 @@ module Kameleon
186
188
  end
187
189
  end
188
190
  end
191
+ Kameleon.ui.info("Step #{macrostep.name} took: #{Time.now.to_i-macrostep_time} secs")
189
192
  end
190
193
  @cleaned_sections.push(section.name)
191
194
  end
@@ -235,7 +238,7 @@ module Kameleon
235
238
  end
236
239
  first_context = map[first_cmd.key]
237
240
  second_context = map[second_cmd.key]
238
- @cache.cache_cmd_id(cmd.identifier) if @cache
241
+ @cache.cache_cmd_raw(cmd.raw_cmd_id) if @cache
239
242
  first_context.pipe(first_cmd.value, second_cmd.value, second_context)
240
243
  when "rescue"
241
244
  first_cmd, second_cmd = cmd.value
@@ -1,6 +1,7 @@
1
1
  require 'childprocess'
2
2
  require 'singleton'
3
3
  require 'socket'
4
+
4
5
  module Kameleon
5
6
  #This ruby class will control the execution of Polipo web proxy
6
7
  class Persistent_cache
@@ -36,6 +37,7 @@ module Kameleon
36
37
  :proxyPort => @polipo_port,
37
38
  :relaxTransparency =>"true",
38
39
  :daemonise => false,
40
+ :proxyAddress => "0.0.0.0",
39
41
  :logFile => File.join(Kameleon.env.build_path, 'polipo.log')
40
42
  }
41
43
 
@@ -45,10 +47,9 @@ module Kameleon
45
47
  @cache_dir = Kameleon.env.cache_path
46
48
  @polipo_path = nil
47
49
  @cwd = ""
48
- #structure {:cmd => "cmd", :stdout_filename => "file_name"}
49
50
  @cmd_cached = []
50
51
  @cache_path = ""
51
- @current_cmd_id = nil
52
+ @current_raw_cmd = nil
52
53
  @current_step_dir = nil
53
54
  @recipe_file = nil
54
55
  @steps_files = []
@@ -93,7 +94,7 @@ module Kameleon
93
94
 
94
95
  def create_cache_directory(step_name)
95
96
  Kameleon.ui.debug("Creating cache directory #{step_name} for Polipo")
96
- directory_name = File.join(@cache_dir,"#{step_name}")
97
+ directory_name = File.join(@cache_dir,"DATA","#{step_name}")
97
98
  FileUtils.mkdir_p directory_name
98
99
  directory_name
99
100
  end
@@ -135,10 +136,9 @@ module Kameleon
135
136
  end
136
137
 
137
138
 
138
- # This function caches the command with its respective stdout
139
- # a command id is associate to a file
140
- def cache_cmd_id(cmd_identifier)
141
- @current_cmd_id = cmd_identifier
139
+ # This function caches the raw command specified in the recipe
140
+ def cache_cmd_raw(raw_cmd_id)
141
+ @current_raw_cmd = raw_cmd_id
142
142
  return true
143
143
  end
144
144
 
@@ -147,16 +147,18 @@ module Kameleon
147
147
  Kameleon.ui.debug("command: cp #{file_path} #{@cwd}/cache/files/")
148
148
  FileUtils.mkdir_p @current_step_dir + "/data/"
149
149
  FileUtils.cp file_path, @current_step_dir + "/data/"
150
- @cmd_cached.push({:cmd_id => @current_cmd_id,
151
- :cmd => cmd ,
150
+ @cmd_cached.push({:raw_cmd_id => @current_raw_cmd,
152
151
  :stdout_filename => File.basename(file_path)})
153
152
  end
154
153
 
155
154
  def get_cache_cmd(cmd)
156
155
  return false if @mode == :build
157
- cache_line = @cmd_cached.select{ |reg|
158
- (reg[:cmd_id] == @current_cmd_id && reg[:cmd] == cmd) }.first
159
-
156
+ cache_line = @cmd_cached.select{ |reg| reg[:raw_cmd_id] == @current_raw_cmd }.first
157
+ if cache_line.nil? then
158
+ # This error can be due to the improper format of the file cache_cmd_index
159
+ Kameleon.ui.error("Persistent cache missing file")
160
+ raise BuildError, "Failed to use persistent cache"
161
+ end
160
162
  return File.new("#{@current_step_dir}/data/#{cache_line[:stdout_filename]}","r")
161
163
  end
162
164
 
@@ -164,22 +166,34 @@ module Kameleon
164
166
  @polipo_process.stop
165
167
  Kameleon.ui.info("Stopping web proxy polipo")
166
168
  Kameleon.ui.info("Finishing persistent cache with last files")
167
-
169
+ cache_metadata_dir = File.join(@cache_dir,"metadata")
168
170
  if @mode == :build then
169
- File.open("#{@cache_dir}/cache_cmd_index",'w+') do |f|
171
+ File.open("#{cache_metadata_dir}/cache_cmd_index",'w+') do |f|
170
172
  f.puts(@cmd_cached.to_yaml)
171
173
  end
172
174
 
173
175
  unless @recipe_files.empty?
174
- recipe_dir = Pathname.new(common_prefix(@recipe_files))
175
176
  all_files = @recipe_files.push(@recipe_path)
176
- Kameleon::Utils.copy_files(recipe_dir, @cache_dir, all_files)
177
+ recipe_dir = Pathname.new(common_prefix(all_files))
178
+ cached_recipe_dir = Pathname.new(File.join(@cache_dir,"recipe"))
179
+ # binding.pry
180
+ Kameleon::Utils.copy_files(recipe_dir, cached_recipe_dir, all_files)
177
181
  end
178
182
  ## Saving metadata information
179
183
  Kameleon.ui.info("Caching recipe")
180
- File.open("#{@cached_recipe_dir}/header",'w+') do |f|
181
- f.puts({:recipe_path => @recipe_path.to_s}.to_yaml)
184
+
185
+ File.open("#{cache_metadata_dir}/header",'w+') do |f|
186
+ f.puts({:recipe_path => @recipe_path.basename.to_s}.to_yaml)
187
+ f.puts({:date => Time.now.to_i}.to_yaml)
188
+ end
189
+
190
+ #Removing empty directories
191
+ cache_data_dir = File.join(@cache_dir,"DATA")
192
+ Dir.foreach(cache_data_dir) do |item|
193
+ dir_temp = File.join(cache_data_dir,item)
194
+ Dir.delete(dir_temp) if File.stat(dir_temp).nlink == 2
182
195
  end
196
+
183
197
  pack
184
198
  end
185
199
  end
@@ -193,20 +207,24 @@ module Kameleon
193
207
  raise BuildError, "Failed to untar the persistent cache file"
194
208
  end
195
209
  ## We have to load the file
196
- @cmd_cached = YAML.load(File.read("#{@cache_dir}/cache_cmd_index"))
210
+ metadata_dir = File.join(@cache_dir,"metadata")
211
+ @cmd_cached = YAML.load(File.read("#{metadata_dir}/cache_cmd_index"))
197
212
  end
198
213
  @activated = true
199
- @cached_recipe_dir = @cache_dir
200
- FileUtils.mkdir_p @cached_recipe_dir
214
+ #@cached_recipe_dir = @cache_dir
215
+ FileUtils.mkdir_p @cache_dir
216
+ # Creating sctructure of the cache
217
+ FileUtils.mkdir_p File.join(@cache_dir,"recipe")
218
+ FileUtils.mkdir_p File.join(@cache_dir,"DATA")
219
+ FileUtils.mkdir_p File.join(@cache_dir,"metadata")
201
220
  end
202
221
 
203
222
  def get_recipe()
204
223
  cached_recipe=Dir.mktmpdir("cache")
205
- puts "cache path : #{@cache_path}"
206
- execute("tar","-xf #{@cache_path} -C #{cached_recipe} .")
224
+ execute("tar","-xf #{@cache_path} -C #{cached_recipe} ./recipe ./metadata")
207
225
  Kameleon.ui.info("Getting cached recipe")
208
- recipe_header = YAML::load(File.read("#{cached_recipe}/header"))
209
- recipe_file = recipe_header[:recipe_path]
226
+ recipe_header = YAML::load(File.read(File.join(cached_recipe,"metadata","header")))
227
+ recipe_file = File.join(cached_recipe,"recipe",recipe_header[:recipe_path])
210
228
  return recipe_file
211
229
  end
212
230
 
@@ -327,13 +327,6 @@ module Kameleon
327
327
  consistency_check
328
328
  resolve_checkpoint unless @checkpoint.nil?
329
329
 
330
- Kameleon.ui.info("Resolving variables")
331
- @sections.values.each do |section|
332
- section.macrosteps.each do |macrostep|
333
- macrostep.resolve_variables!(@global)
334
- end
335
- end
336
-
337
330
  @sections.values.each do |section|
338
331
  section.macrosteps.each do |macrostep|
339
332
  # First pass : resolve aliases
@@ -347,6 +340,18 @@ module Kameleon
347
340
  # flatten for multiple-command alias + variables
348
341
  Kameleon.ui.debug("Resolving check statements for macrostep '#{macrostep.name}'")
349
342
  macrostep.microsteps.each { |microstep| microstep.commands.flatten! }
343
+ end
344
+ end
345
+
346
+ Kameleon.ui.info("Resolving variables")
347
+ @sections.values.each do |section|
348
+ section.macrosteps.each do |macrostep|
349
+ macrostep.resolve_variables!(@global)
350
+ end
351
+ end
352
+
353
+ @sections.values.each do |section|
354
+ section.macrosteps.each do |macrostep|
350
355
  # Second pass : resolve variables + clean/init hooks
351
356
  macrostep.microsteps.each do |microstep|
352
357
  microstep.commands.map! do |cmd|
@@ -3,11 +3,13 @@ module Kameleon
3
3
  class Command
4
4
 
5
5
  attr_accessor :string_cmd
6
+ attr_accessor :raw_cmd_id
6
7
  attr_accessor :microstep_name
7
8
  attr_accessor :identifier
8
9
 
9
10
  def initialize(yaml_cmd, microstep_name)
10
11
  @string_cmd = YAML.dump(yaml_cmd).gsub("---", "").strip
12
+ @raw_cmd_id = Digest::SHA1.hexdigest(YAML.dump(yaml_cmd).gsub("---", "").strip)
11
13
  @microstep_name = microstep_name
12
14
  @identifier = nil
13
15
  end
@@ -50,7 +50,10 @@ global:
50
50
  - $$distrib
51
51
  - "fedora"
52
52
 
53
- disable_selinux: true
53
+ # SELinux configuration
54
+ selinux: permissive ## Can take one of these three values: enforcing, permissive or disabled
55
+ selinuxtype: targeted # Possible values are: strict, targeted
56
+
54
57
  ssh_config_file: $$kameleon_cwd/ssh_config
55
58
  out_context:
56
59
  cmd: ssh -F $$ssh_config_file $${kameleon_recipe_name} -t /bin/bash
@@ -58,7 +61,7 @@ global:
58
61
  proxy_cache: 10.0.2.2
59
62
 
60
63
  in_context:
61
- cmd: ssh -F $$ssh_config_file $${kameleon_recipe_name} -t chroot $$rootfs /bin/bash
64
+ cmd: ssh -F $$ssh_config_file $${kameleon_recipe_name} -t /bin/bash
62
65
  workdir: /root/kameleon_workdir
63
66
  proxy_cache: 10.0.2.2
64
67
 
@@ -67,12 +70,14 @@ bootstrap:
67
70
  - prepare_qemu
68
71
  - start_qemu
69
72
  - install_requirements:
70
- - packages: parted e2fsprogs yum rpm lynx
71
- - initialize_disk:
73
+ - packages: parted e2fsprogs yum rpm lynx extlinux
74
+ - initialize_disk
72
75
  - yum_bootstrap:
73
76
  - mirror_packages_url: http://mirrors.kernel.org/$$distrib/$$release/os/$$arch/Packages/
74
- - include_pkgs: findutils util-linux
75
- - start_chroot
77
+ - include_pkgs: >
78
+ findutils yum util-linux dhclient vim-minimal net-tools openssh-server
79
+ kernel kernel-devel acpid
80
+ - switch_context_qemu
76
81
 
77
82
  #== Install and configuration steps
78
83
  setup:
@@ -81,9 +86,13 @@ setup:
81
86
  - minimal_install
82
87
  - install_software:
83
88
  - packages: >
84
- kernel kernel-devel syslinux-extlinux bash-completion kbd dhclient
85
- sudo openssh-server openssh-clients ntp ntpdate dhclient
86
- net-tools NetworkManager
89
+ syslinux-extlinux kbd sudo openssh-clients ntp ntpdate
90
+ rsync bridge-utils bzip2 cronie cronie-anacron crontabs
91
+ dash dhclient dhcp-common dracut dracut-kernel file fuse gnupg2
92
+ iptables-ipv6 libuser logrotate m4 openssh-server passwd
93
+ pciutils-libs rsyslog dbus system-config-firewall-base which
94
+ findutils yum util-linux vim-minimal net-tools openssh-server
95
+ kernel kernel-devel acpid
87
96
  - install_bootloader
88
97
  - configure_system:
89
98
  - locales: POSIX C en_US fr_FR de_DE
@@ -50,7 +50,10 @@ global:
50
50
  - $$distrib
51
51
  - "fedora"
52
52
 
53
- disable_selinux: true
53
+ # SELinux configuration
54
+ selinux: permissive ## Can take one of these three values: enforcing, permissive or disabled
55
+ selinuxtype: targeted # Possible values are: strict, targeted
56
+
54
57
  ssh_config_file: $$kameleon_cwd/ssh_config
55
58
  out_context:
56
59
  cmd: ssh -F $$ssh_config_file $${kameleon_recipe_name} -t /bin/bash
@@ -49,7 +49,10 @@ global:
49
49
  - $$distrib/$$release
50
50
  - $$distrib
51
51
 
52
- disable_selinux: true
52
+ # SELinux configuration
53
+ selinux: permissive ## Can take one of these three values: enforcing, permissive or disabled
54
+ selinuxtype: targeted # Possible values are: strict, targeted
55
+
53
56
  ssh_config_file: $$kameleon_cwd/ssh_config
54
57
  out_context:
55
58
  cmd: ssh -F $$ssh_config_file $${kameleon_recipe_name} -t /bin/bash
@@ -0,0 +1,65 @@
1
+ - fix_yum:
2
+ - check_cmd_out: yum
3
+ - exec_out: sed -i "s/opts.ssl_verify_host/2/g" /usr/lib/pymodules/python2.7/urlgrabber/grabber.py
4
+
5
+ - init_rpm_db:
6
+ - check_cmd_out: rpm
7
+ - exec_out: mkdir -p $$rootfs/var/lib/rpm
8
+ - exec_out: rpm --root $$rootfs --initdb
9
+
10
+ - fetch_release_package:
11
+ - check_cmd_out: lynx
12
+ - exec_out: RELEASE_PACKAGE_URL=$(lynx $$mirror_packages_url -dump -listonly -nonumbers | grep $${distrib}-release | head -1)
13
+ - exec_out: |
14
+ if [ -z "${RELEASE_PACKAGE_URL-unset}" ]; then
15
+ fail "$${distrib}-release package not found!"
16
+ fi
17
+
18
+ - install_distrib_release:
19
+ - download_file_out:
20
+ - $RELEASE_PACKAGE_URL
21
+ - $KAMELEON_WORKDIR/$${distrib}-release.rpm
22
+ - exec_out: rpm --root $$rootfs -ivh --force-debian --nodeps $KAMELEON_WORKDIR/$${distrib}-release.rpm
23
+
24
+ - install_yum:
25
+ - exec_out: ln -sf $$rootfs/etc/pki/ /etc/pki
26
+ - exec_out: yum --installroot $$rootfs -y install yum
27
+ - exec_out: echo $${release} > $$rootfs/etc/yum/vars/releasever
28
+
29
+ - mount_chroot:
30
+ - exec_out: mount -o bind /dev $$rootfs/dev
31
+ - exec_out: mount -o bind /dev/pts $$rootfs/dev/pts
32
+ - exec_out: mount -t proc /proc $$rootfs/proc
33
+ - exec_out: mount -t sysfs /sys $$rootfs/sys
34
+ - exec_out: cp /etc/resolv.conf $$rootfs/etc/resolv.conf
35
+
36
+ - install_packages:
37
+ - exec_out: chroot $$rootfs yum install --releasever=$$release -y $$include_pkgs
38
+
39
+ - enable_services:
40
+ - exec_out: chroot $$rootfs chkconfig network on
41
+ - exec_out: chroot $$rootfs chkconfig sshd on
42
+
43
+ - set_interface:
44
+ - write_out:
45
+ - $$rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
46
+ - |
47
+ DEVICE=eth0
48
+ BOOTPROTO=dhcp
49
+ ONBOOT=yes
50
+ HOSTNAME=$$hostname
51
+ NM_CONTROLLED=no
52
+ TYPE=Ethernet
53
+ - write_out:
54
+ - $$rootfs/etc/sysconfig/network
55
+ - |
56
+ NETWORKING=yes
57
+ HOSTNAME=$$hostname
58
+
59
+ - umount_chroot:
60
+ - on_clean:
61
+ - umount_out: $$rootfs/sys
62
+ - umount_out: $$rootfs/proc
63
+ - umount_out: $$rootfs/dev/pts
64
+ - umount_out: $$rootfs/dev
65
+ - exec_out: rm -f $$rootfs/etc/resolv.conf
@@ -22,6 +22,7 @@
22
22
  -cdrom $$kameleon_cwd/boot2kameleon.iso \
23
23
  -drive file="$$qemu_image_disk",cache=unsafe,media=disk,if=virtio,id=drive0 \
24
24
  -smp $${qemu_cpu} \
25
+ -cpu host \
25
26
  -m $$qemu_memory_size \
26
27
  -rtc base=localtime \
27
28
  -net nic,model=virtio -net user \
@@ -31,13 +32,14 @@
31
32
  -daemonize -vnc :1 $LOADVM
32
33
  - exec_local: |
33
34
  NEXT_WAIT_TIME=0
34
- until ssh-keyscan -T 1 -4 -p $$qemu_ssh_port localhost 2>&1 | grep -e ssh-rsa -e ssh-dsa &> /dev/null || [ $NEXT_WAIT_TIME -eq $$boot_timeout ];
35
+ SSH_AVAILABLE=0
36
+ until ssh-keyscan -T 1 -4 -p $$qemu_ssh_port localhost 2>&1 | grep -e ssh-rsa -e ssh-dsa &> /dev/null && SSH_AVAILABLE=1 || [ $NEXT_WAIT_TIME -eq $$boot_timeout ];
35
37
  do
36
38
  echo -en "\rWaiting for SSH to become available for out_context...($(( $$boot_timeout - 1 - NEXT_WAIT_TIME++ ))s)"
37
39
  done
38
40
  echo ""
39
41
  - rescue:
40
- - exec_local: ssh-keyscan -T 1 -4 -p $$qemu_ssh_port localhost 2>&1 | grep -e ssh-rsa -e ssh-dsa &> /dev/null
42
+ - exec_local: test $SSH_AVAILABLE -eq 1
41
43
  - breakpoint: Failed to connect to VM via SSH. Please verify the VM successfully booted with a vnc client.
42
44
 
43
45
  - force_shutdown_qemu_vm: