pennyworth-tool 0.0.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.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.hound.yml +3 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +18 -0
  6. data/CONTRIBUTING.md +67 -0
  7. data/COPYING +674 -0
  8. data/Gemfile +28 -0
  9. data/README.md +339 -0
  10. data/Rakefile +33 -0
  11. data/bin/pennyworth +26 -0
  12. data/config/setup.yml +17 -0
  13. data/examples/README.md +23 -0
  14. data/examples/kiwi/definitions/base_opensuse13.1_kvm/config.sh +87 -0
  15. data/examples/kiwi/definitions/base_opensuse13.1_kvm/config.xml +64 -0
  16. data/examples/kiwi/definitions/base_opensuse13.1_kvm/root/etc/sysconfig/network/ifcfg-eth0 +2 -0
  17. data/examples/kiwi/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  18. data/examples/vagrant/Vagrantfile +14 -0
  19. data/files/99-libvirt.rules +2 -0
  20. data/files/image_test-template.xml +43 -0
  21. data/files/pool-default.xml +6 -0
  22. data/lib/image_runner.rb +89 -0
  23. data/lib/pennyworth.rb +65 -0
  24. data/lib/pennyworth/cli.rb +339 -0
  25. data/lib/pennyworth/cli_host_controller.rb +107 -0
  26. data/lib/pennyworth/commands/base_command.rb +96 -0
  27. data/lib/pennyworth/commands/boot_command.rb +29 -0
  28. data/lib/pennyworth/commands/build_base_command.rb +103 -0
  29. data/lib/pennyworth/commands/command.rb +43 -0
  30. data/lib/pennyworth/commands/down_command.rb +25 -0
  31. data/lib/pennyworth/commands/import_base_command.rb +112 -0
  32. data/lib/pennyworth/commands/import_ssh_keys_command.rb +27 -0
  33. data/lib/pennyworth/commands/list_command.rb +41 -0
  34. data/lib/pennyworth/commands/setup_command.rb +209 -0
  35. data/lib/pennyworth/commands/shutdown_command.rb +28 -0
  36. data/lib/pennyworth/commands/status_command.rb +26 -0
  37. data/lib/pennyworth/commands/up_command.rb +27 -0
  38. data/lib/pennyworth/exceptions.rb +39 -0
  39. data/lib/pennyworth/helper.rb +39 -0
  40. data/lib/pennyworth/host_config.rb +86 -0
  41. data/lib/pennyworth/host_runner.rb +133 -0
  42. data/lib/pennyworth/image_runner.rb +89 -0
  43. data/lib/pennyworth/libvirt.rb +93 -0
  44. data/lib/pennyworth/local_command_runner.rb +77 -0
  45. data/lib/pennyworth/local_runner.rb +34 -0
  46. data/lib/pennyworth/lock_service.rb +87 -0
  47. data/lib/pennyworth/remote_command_runner.rb +144 -0
  48. data/lib/pennyworth/runner.rb +27 -0
  49. data/lib/pennyworth/settings.rb +42 -0
  50. data/lib/pennyworth/spec.rb +96 -0
  51. data/lib/pennyworth/spec_profiler.rb +85 -0
  52. data/lib/pennyworth/ssh_keys_importer.rb +107 -0
  53. data/lib/pennyworth/urls.rb +28 -0
  54. data/lib/pennyworth/vagrant.rb +81 -0
  55. data/lib/pennyworth/vagrant_command.rb +120 -0
  56. data/lib/pennyworth/vagrant_runner.rb +44 -0
  57. data/lib/pennyworth/version.rb +22 -0
  58. data/lib/pennyworth/vm.rb +62 -0
  59. data/man/.gitignore +2 -0
  60. data/man/pennyworth.1.md +28 -0
  61. data/pennyworth.gemspec +57 -0
  62. data/prophet/Gemfile +3 -0
  63. data/prophet/prophet.rb +82 -0
  64. data/spec/base_command_spec.rb +30 -0
  65. data/spec/build_base_command_spec.rb +147 -0
  66. data/spec/cli_host_controller_spec.rb +113 -0
  67. data/spec/data/hosts.yaml +10 -0
  68. data/spec/data/kiwi/base_opensuse12.3_kvm.box +1 -0
  69. data/spec/data/kiwi/base_opensuse13.1_kvm.box +1 -0
  70. data/spec/data/kiwi/definitions/base_opensuse12.3_kvm/config.sh +1 -0
  71. data/spec/data/kiwi/definitions/base_opensuse12.3_kvm/config.xml +1 -0
  72. data/spec/data/kiwi/definitions/base_opensuse12.3_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  73. data/spec/data/kiwi/definitions/base_opensuse13.1_kvm/config.sh +1 -0
  74. data/spec/data/kiwi/definitions/base_opensuse13.1_kvm/config.xml +1 -0
  75. data/spec/data/kiwi/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  76. data/spec/data/kiwi2/box_state.yaml +14 -0
  77. data/spec/data/kiwi2/definitions/base_opensuse12.3_kvm/config.sh +1 -0
  78. data/spec/data/kiwi2/definitions/base_opensuse12.3_kvm/config.xml +1 -0
  79. data/spec/data/kiwi2/definitions/base_opensuse12.3_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  80. data/spec/data/kiwi2/definitions/base_opensuse13.1_kvm/config.sh +1 -0
  81. data/spec/data/kiwi2/definitions/base_opensuse13.1_kvm/config.xml +1 -0
  82. data/spec/data/kiwi2/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  83. data/spec/data/kiwi3/box_state.yaml +13 -0
  84. data/spec/data/kiwi3/definitions/base_opensuse12.3_kvm/.gitkeep +0 -0
  85. data/spec/data/kiwi3/definitions/base_opensuse13.1_kvm/.gitkeep +0 -0
  86. data/spec/data/kiwi3/import_state.yaml +3 -0
  87. data/spec/data/kiwi4/definitions/base_opensuse12.3_kvm/.gitkeep +0 -0
  88. data/spec/data/kiwi4/definitions/base_opensuse13.1_kvm/.gitkeep +0 -0
  89. data/spec/data/kiwi4/import_state.yaml +3 -0
  90. data/spec/data/kiwi5/import_state.yaml +3 -0
  91. data/spec/data/vagrant/.gitkeep +0 -0
  92. data/spec/host_config_spec.rb +197 -0
  93. data/spec/host_runner_spec.rb +112 -0
  94. data/spec/image_runner_spec.rb +62 -0
  95. data/spec/import_base_command_spec.rb +189 -0
  96. data/spec/local_command_runner_spec.rb +117 -0
  97. data/spec/local_runner_spec.rb +42 -0
  98. data/spec/lock_service_spec.rb +95 -0
  99. data/spec/remote_command_runner_spec.rb +115 -0
  100. data/spec/settings_spec.rb +26 -0
  101. data/spec/setup_command_spec.rb +49 -0
  102. data/spec/spec_helper.rb +50 -0
  103. data/spec/spec_profiler_spec.rb +63 -0
  104. data/spec/spec_spec.rb +99 -0
  105. data/spec/support/command_runner_examples.rb +29 -0
  106. data/spec/support/runner_examples.rb +34 -0
  107. data/spec/urls_spec.rb +46 -0
  108. data/spec/vagrant_command_spec.rb +51 -0
  109. data/spec/vagrant_runner_spec.rb +40 -0
  110. data/spec/vagrant_spec.rb +288 -0
  111. data/spec/vm_spec.rb +56 -0
  112. metadata +257 -0
@@ -0,0 +1,107 @@
1
+ # Copyright (c) 2013-2015 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ module Pennyworth
19
+ class CliHostController
20
+ def initialize(config_dir, output)
21
+ @config_dir = config_dir
22
+ @out = output
23
+ end
24
+
25
+ def setup(url)
26
+ if !url
27
+ raise GLI::BadCommandLine.new("Please provide a URL argument")
28
+ end
29
+
30
+ @out.puts "Setup from '#{url}'"
31
+ begin
32
+ HostConfig.for_directory(@config_dir).setup(url)
33
+ rescue HostFileError => e
34
+ @out.puts "Error: #{e}"
35
+ end
36
+ end
37
+
38
+ def list
39
+ host_config.hosts.each do |host_name|
40
+ host = host_config.host(host_name)
41
+ out = "#{host_name}"
42
+ attributes = []
43
+ if host['address']
44
+ attributes.push("address: #{host['address']}")
45
+ end
46
+ if host['base_snapshot_id']
47
+ attributes.push("base snapshot id: #{host['base_snapshot_id']}")
48
+ end
49
+ if !attributes.empty?
50
+ out += " (" + attributes.join(", ") + ")"
51
+ end
52
+ @out.puts(out)
53
+ end
54
+ end
55
+
56
+ def lock(host_name)
57
+ check_host(host_name)
58
+
59
+ locker = LockService.new(host_config.lock_server_address)
60
+ if locker.request_lock(host_name)
61
+ @out.puts "Lock acquired for host '#{host_name}'"
62
+
63
+ locker.keep_lock
64
+ else
65
+ @out.puts "Failed to acquire lock for host '#{host_name}': " +
66
+ "#{locker.info(host_name)}"
67
+ end
68
+ end
69
+
70
+ def info(host_name)
71
+ check_host(host_name)
72
+
73
+ locker = LockService.new(host_config.lock_server_address)
74
+ @out.puts(locker.info(host_name))
75
+ end
76
+
77
+ def reset(host_name)
78
+ check_host(host_name)
79
+
80
+ runner = HostRunner.new(host_name, host_config)
81
+ runner.start
82
+ runner.cleanup
83
+ end
84
+
85
+ private
86
+
87
+ def check_host(host_name)
88
+ if !host_name
89
+ raise GLI::BadCommandLine.new("Please provide a host name argument")
90
+ end
91
+
92
+ if !host_config.host(host_name)
93
+ raise LockError.new("Host name #{host_name} doesn't exist in " +
94
+ "configuration file '#{host_config.config_file}'")
95
+ end
96
+ end
97
+
98
+ def host_config
99
+ return @host_config if @host_config
100
+
101
+ @host_config = HostConfig.for_directory(@config_dir)
102
+ @host_config.read
103
+
104
+ @host_config
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,96 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ module Pennyworth
19
+ class BaseCommand < Command
20
+
21
+ attr_reader :kiwi_dir
22
+
23
+ def initialize(kiwi_dir, remote_url = nil)
24
+ super()
25
+ @kiwi_dir = kiwi_dir
26
+ @remote_url = remote_url
27
+ end
28
+
29
+ def remote_base_images(subdir = "")
30
+ return [] if !@remote_url || @remote_url.empty?
31
+
32
+ uri = URI.parse(URLs.join(@remote_url, subdir, "import_state.yaml"))
33
+ response = Net::HTTP.get_response(uri)
34
+ if response.is_a?(Net::HTTPSuccess)
35
+ index = YAML.load(response.body)
36
+ index.keys
37
+ else
38
+ STDERR.puts "Could not download remote state file at #{uri.to_s}: " + response.message
39
+ exit 1
40
+ end
41
+ end
42
+
43
+ def local_base_images
44
+ Dir.glob(File.join(@kiwi_dir, "definitions", "*")).
45
+ select { |f| File.directory?(f) }.
46
+ map { |d| File.basename(d) }
47
+ end
48
+
49
+ def process_base_image_parameter(all_images, base_image = nil)
50
+ if !base_image
51
+ return all_images
52
+ end
53
+ if all_images.include?(base_image)
54
+ return [base_image]
55
+ else
56
+ raise "Unknown base image '#{base_image}'. Known images are: #{all_images.join(", ")}."
57
+ end
58
+ end
59
+
60
+ def read_box_sources_state(box_name)
61
+ sources = Hash.new
62
+ source_dir = File.join(@kiwi_dir, "definitions", box_name)
63
+ Find.find(source_dir) do |file|
64
+ next if File.directory?(file)
65
+ relative_path = file.gsub(/^#{File.join(source_dir, "/")}/, "")
66
+ sources[relative_path] = Digest::MD5.file(file).hexdigest
67
+ end
68
+ sources
69
+ end
70
+
71
+ def read_box_target_state(box_name)
72
+ box_file = File.join(@kiwi_dir, box_name) + ".box"
73
+ if File.exist?(box_file)
74
+ target_state = Digest::MD5.file(box_file).hexdigest
75
+ end
76
+ target_state
77
+ end
78
+
79
+ def write_box_state_file(box_state)
80
+ File.open(File.join(@kiwi_dir, "box_state.yaml"), "w") do |f|
81
+ f.write(box_state.to_yaml)
82
+ end
83
+ end
84
+
85
+ def read_local_box_state_file
86
+ box_state_file = File.join(@kiwi_dir, "box_state.yaml")
87
+ if File.exist? box_state_file
88
+ box_state = YAML.load_file(box_state_file)
89
+ else
90
+ box_state = {}
91
+ end
92
+ box_state
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ module Pennyworth
19
+ class BootCommand < Command
20
+ def execute(image)
21
+ runner = ImageRunner.new(image)
22
+ log "Starting image #{runner.name}"
23
+
24
+ ip = VM.new(runner).start
25
+
26
+ log "System was started with IP #{ip}."
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,103 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ module Pennyworth
19
+ class BuildBaseCommand < BaseCommand
20
+
21
+ def initialize(kiwi_dir)
22
+ super
23
+ end
24
+
25
+ def execute(tmp_dir, image_name = nil)
26
+ Pennyworth::Libvirt.ensure_libvirt_env_started
27
+
28
+ box_state = read_local_box_state_file
29
+ images = process_base_image_parameter(local_base_images, image_name)
30
+ log "Creating base images..."
31
+ images.each do |image|
32
+ Dir.chdir kiwi_dir do
33
+ log
34
+ log "--- #{image} ---"
35
+ source_state = read_box_sources_state(image)
36
+ if box_state[image] && box_state[image]["sources"] &&
37
+ source_state && box_state[image]["sources"] == source_state
38
+ log " Sources not changed, skipping build"
39
+ else
40
+ log " Building base image..."
41
+ base_image_create(File.join(kiwi_dir, "definitions", image), tmp_dir)
42
+ log " Exporting image as box for vagrant..."
43
+ base_image_export(File.join(kiwi_dir, image), tmp_dir)
44
+ base_image_cleanup_build(tmp_dir)
45
+
46
+ box_state[image] = {
47
+ "sources" => source_state,
48
+ "target" => read_box_target_state(image)
49
+ }
50
+ write_box_state_file(box_state)
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ # Creates a KVM image from the according Kiwi description.
59
+ # See pennyworth/kiwi/definitions for the definitions we use.
60
+ def base_image_create(description_dir, tmp_dir)
61
+ FileUtils.mkdir_p(tmp_dir)
62
+ logfile = "#{tmp_dir}/kiwi-terminal-output.log"
63
+ log " The build log is available under #{logfile}"
64
+ begin
65
+ Cheetah.run "sudo", "/usr/sbin/kiwi", "--build", description_dir,
66
+ "--destdir", tmp_dir, "--logfile", "#{logfile}",
67
+ :stdout => :capture
68
+ rescue Cheetah::ExecutionFailed => e
69
+ raise ExecutionFailed.new(e)
70
+ end
71
+ end
72
+
73
+ def base_image_export(kiwi_dir, tmp_dir)
74
+ Dir.chdir(tmp_dir) do
75
+ image = Dir.glob("*.box").first
76
+ if image
77
+ from_file = File.join(tmp_dir, image)
78
+ to_file = kiwi_dir.gsub(/\/$/, "") + ".box"
79
+ begin
80
+ Cheetah.run "sudo", "mv", from_file, to_file, :stdout => :capture
81
+ rescue Cheetah::ExecutionFailed => e
82
+ raise ExecutionFailed.new(e)
83
+ end
84
+ else
85
+ raise BuildFailed, "The built image couldn't be found."
86
+ end
87
+ end
88
+ end
89
+
90
+ def base_image_cleanup_build(tmp_dir)
91
+ if tmp_dir.start_with?("/tmp/")
92
+ begin
93
+ Cheetah.run "sudo", "rm", "-r", tmp_dir, :stdout => :capture
94
+ rescue Cheetah::ExecutionFailed => e
95
+ raise ExecutionFailed.new(e)
96
+ end
97
+ else
98
+ log " Warning: The KIWI tmp dir #{tmp_dir} was outside of '/tmp' so it" \
99
+ " wasn't removed!"
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,43 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ module Pennyworth
19
+ class Command
20
+
21
+ def initialize
22
+ Cheetah.default_options = { :logger => logger }
23
+ end
24
+
25
+ def config
26
+ @config ||= YAML.load_file(File.dirname(__FILE__) + "/../../../config/setup.yml")
27
+ end
28
+
29
+ def logger
30
+ @logger ||= Logger.new("/tmp/pennyworth.log")
31
+ end
32
+
33
+ private
34
+
35
+ def print_ssh_config(vagrant, vm_name)
36
+ config = vagrant.ssh_config(vm_name)
37
+
38
+ config.each_pair do |host, host_config|
39
+ puts "#{host}\t#{host_config["HostName"]}"
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ module Pennyworth
19
+ class DownCommand < Command
20
+ def execute(vm_name = nil)
21
+ v = VagrantCommand.new
22
+ v.down vm_name
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,112 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ module Pennyworth
19
+ class ImportBaseCommand < BaseCommand
20
+
21
+ def execute(image_name, options = {})
22
+ @vagrant = VagrantCommand.new
23
+ options = {
24
+ subdir: "",
25
+ local: false
26
+ }.merge(options)
27
+
28
+ Pennyworth::Libvirt.ensure_libvirt_env_started
29
+
30
+ if options[:local]
31
+ all_images = local_base_images
32
+ box_state = read_local_box_state_file
33
+ else
34
+ all_images = remote_base_images(options[:subdir])
35
+ box_state = read_remote_box_state_file
36
+ end
37
+ import_state = read_import_state_file
38
+ images = process_base_image_parameter(all_images, image_name)
39
+ images.each do |image|
40
+ if box_state[image] && box_state[image]["target"] &&
41
+ import_state[image] &&
42
+ box_state[image]["target"] == import_state[image]
43
+ log "Box '#{image}' hasn't changed since last import. Skipping"
44
+ else
45
+ Dir.chdir Cli.settings.vagrant_dir do
46
+ log "Importing box '#{image}' into vagrant..."
47
+ base_image_clean(image)
48
+ base_image_import(image, options)
49
+ if box_state[image] && box_state[image]["target"]
50
+ import_state[image] = box_state[image]["target"]
51
+ else
52
+ import_state[image] = nil
53
+ end
54
+ write_import_state_file(import_state)
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ def read_import_state_file
61
+ import_state_file = File.join(kiwi_dir, "import_state.yaml")
62
+ if File.exist? import_state_file
63
+ import_state = YAML.load_file(import_state_file)
64
+ else
65
+ import_state = {}
66
+ end
67
+ import_state
68
+ end
69
+
70
+ def write_import_state_file(import_state)
71
+ FileUtils.mkdir_p(kiwi_dir) unless Dir.exists?(kiwi_dir)
72
+
73
+ File.open(File.join(kiwi_dir, "import_state.yaml"), "w") do |f|
74
+ f.write(import_state.to_yaml)
75
+ end
76
+ end
77
+
78
+ def read_remote_box_state_file
79
+ box_state_yaml = fetch_remote_box_state_file
80
+ if box_state_yaml
81
+ return YAML.load(box_state_yaml)
82
+ else
83
+ return {}
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def fetch_remote_box_state_file
90
+ url = URLs.join(@remote_url, "box_state.yaml")
91
+ Net::HTTP.get(URI.parse(url))
92
+ end
93
+
94
+ def base_image_clean(box)
95
+ Cheetah.run "virsh", "-c", "qemu:///system", "vol-delete", "#{box}_vagrant_box_image.img", "--pool=default"
96
+ Cheetah.run "virsh", "-c", "qemu:///system", "pool-refresh", "--pool=default"
97
+ @vagrant.destroy
98
+ rescue
99
+ end
100
+
101
+ # Imports the box into the Vagrant pool so that it can be used for the test
102
+ # environments.
103
+ def base_image_import(box, options)
104
+ if options[:local]
105
+ box_path = File.join(kiwi_dir, box + ".box")
106
+ else
107
+ box_path = URLs.join(@remote_url, options[:subdir], box + ".box")
108
+ end
109
+ @vagrant.add_box(box, box_path)
110
+ end
111
+ end
112
+ end