pennyworth-tool 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.hound.yml +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +18 -0
- data/CONTRIBUTING.md +67 -0
- data/COPYING +674 -0
- data/Gemfile +28 -0
- data/README.md +339 -0
- data/Rakefile +33 -0
- data/bin/pennyworth +26 -0
- data/config/setup.yml +17 -0
- data/examples/README.md +23 -0
- data/examples/kiwi/definitions/base_opensuse13.1_kvm/config.sh +87 -0
- data/examples/kiwi/definitions/base_opensuse13.1_kvm/config.xml +64 -0
- data/examples/kiwi/definitions/base_opensuse13.1_kvm/root/etc/sysconfig/network/ifcfg-eth0 +2 -0
- data/examples/kiwi/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
- data/examples/vagrant/Vagrantfile +14 -0
- data/files/99-libvirt.rules +2 -0
- data/files/image_test-template.xml +43 -0
- data/files/pool-default.xml +6 -0
- data/lib/image_runner.rb +89 -0
- data/lib/pennyworth.rb +65 -0
- data/lib/pennyworth/cli.rb +339 -0
- data/lib/pennyworth/cli_host_controller.rb +107 -0
- data/lib/pennyworth/commands/base_command.rb +96 -0
- data/lib/pennyworth/commands/boot_command.rb +29 -0
- data/lib/pennyworth/commands/build_base_command.rb +103 -0
- data/lib/pennyworth/commands/command.rb +43 -0
- data/lib/pennyworth/commands/down_command.rb +25 -0
- data/lib/pennyworth/commands/import_base_command.rb +112 -0
- data/lib/pennyworth/commands/import_ssh_keys_command.rb +27 -0
- data/lib/pennyworth/commands/list_command.rb +41 -0
- data/lib/pennyworth/commands/setup_command.rb +209 -0
- data/lib/pennyworth/commands/shutdown_command.rb +28 -0
- data/lib/pennyworth/commands/status_command.rb +26 -0
- data/lib/pennyworth/commands/up_command.rb +27 -0
- data/lib/pennyworth/exceptions.rb +39 -0
- data/lib/pennyworth/helper.rb +39 -0
- data/lib/pennyworth/host_config.rb +86 -0
- data/lib/pennyworth/host_runner.rb +133 -0
- data/lib/pennyworth/image_runner.rb +89 -0
- data/lib/pennyworth/libvirt.rb +93 -0
- data/lib/pennyworth/local_command_runner.rb +77 -0
- data/lib/pennyworth/local_runner.rb +34 -0
- data/lib/pennyworth/lock_service.rb +87 -0
- data/lib/pennyworth/remote_command_runner.rb +144 -0
- data/lib/pennyworth/runner.rb +27 -0
- data/lib/pennyworth/settings.rb +42 -0
- data/lib/pennyworth/spec.rb +96 -0
- data/lib/pennyworth/spec_profiler.rb +85 -0
- data/lib/pennyworth/ssh_keys_importer.rb +107 -0
- data/lib/pennyworth/urls.rb +28 -0
- data/lib/pennyworth/vagrant.rb +81 -0
- data/lib/pennyworth/vagrant_command.rb +120 -0
- data/lib/pennyworth/vagrant_runner.rb +44 -0
- data/lib/pennyworth/version.rb +22 -0
- data/lib/pennyworth/vm.rb +62 -0
- data/man/.gitignore +2 -0
- data/man/pennyworth.1.md +28 -0
- data/pennyworth.gemspec +57 -0
- data/prophet/Gemfile +3 -0
- data/prophet/prophet.rb +82 -0
- data/spec/base_command_spec.rb +30 -0
- data/spec/build_base_command_spec.rb +147 -0
- data/spec/cli_host_controller_spec.rb +113 -0
- data/spec/data/hosts.yaml +10 -0
- data/spec/data/kiwi/base_opensuse12.3_kvm.box +1 -0
- data/spec/data/kiwi/base_opensuse13.1_kvm.box +1 -0
- data/spec/data/kiwi/definitions/base_opensuse12.3_kvm/config.sh +1 -0
- data/spec/data/kiwi/definitions/base_opensuse12.3_kvm/config.xml +1 -0
- data/spec/data/kiwi/definitions/base_opensuse12.3_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
- data/spec/data/kiwi/definitions/base_opensuse13.1_kvm/config.sh +1 -0
- data/spec/data/kiwi/definitions/base_opensuse13.1_kvm/config.xml +1 -0
- data/spec/data/kiwi/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
- data/spec/data/kiwi2/box_state.yaml +14 -0
- data/spec/data/kiwi2/definitions/base_opensuse12.3_kvm/config.sh +1 -0
- data/spec/data/kiwi2/definitions/base_opensuse12.3_kvm/config.xml +1 -0
- data/spec/data/kiwi2/definitions/base_opensuse12.3_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
- data/spec/data/kiwi2/definitions/base_opensuse13.1_kvm/config.sh +1 -0
- data/spec/data/kiwi2/definitions/base_opensuse13.1_kvm/config.xml +1 -0
- data/spec/data/kiwi2/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
- data/spec/data/kiwi3/box_state.yaml +13 -0
- data/spec/data/kiwi3/definitions/base_opensuse12.3_kvm/.gitkeep +0 -0
- data/spec/data/kiwi3/definitions/base_opensuse13.1_kvm/.gitkeep +0 -0
- data/spec/data/kiwi3/import_state.yaml +3 -0
- data/spec/data/kiwi4/definitions/base_opensuse12.3_kvm/.gitkeep +0 -0
- data/spec/data/kiwi4/definitions/base_opensuse13.1_kvm/.gitkeep +0 -0
- data/spec/data/kiwi4/import_state.yaml +3 -0
- data/spec/data/kiwi5/import_state.yaml +3 -0
- data/spec/data/vagrant/.gitkeep +0 -0
- data/spec/host_config_spec.rb +197 -0
- data/spec/host_runner_spec.rb +112 -0
- data/spec/image_runner_spec.rb +62 -0
- data/spec/import_base_command_spec.rb +189 -0
- data/spec/local_command_runner_spec.rb +117 -0
- data/spec/local_runner_spec.rb +42 -0
- data/spec/lock_service_spec.rb +95 -0
- data/spec/remote_command_runner_spec.rb +115 -0
- data/spec/settings_spec.rb +26 -0
- data/spec/setup_command_spec.rb +49 -0
- data/spec/spec_helper.rb +50 -0
- data/spec/spec_profiler_spec.rb +63 -0
- data/spec/spec_spec.rb +99 -0
- data/spec/support/command_runner_examples.rb +29 -0
- data/spec/support/runner_examples.rb +34 -0
- data/spec/urls_spec.rb +46 -0
- data/spec/vagrant_command_spec.rb +51 -0
- data/spec/vagrant_runner_spec.rb +40 -0
- data/spec/vagrant_spec.rb +288 -0
- data/spec/vm_spec.rb +56 -0
- metadata +257 -0
@@ -0,0 +1,86 @@
|
|
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 HostConfig
|
20
|
+
attr_reader :config_file, :lock_server_address
|
21
|
+
|
22
|
+
def self.for_directory(config_dir)
|
23
|
+
HostConfig.new(File.join(config_dir, "hosts.yaml"))
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(config_file)
|
27
|
+
@config_file = File.expand_path(config_file)
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse(yaml_string)
|
31
|
+
yaml = YAML.load(yaml_string)
|
32
|
+
if !yaml
|
33
|
+
raise HostFileError.new("Could not parse YAML in file '#{config_file}'")
|
34
|
+
end
|
35
|
+
|
36
|
+
if yaml["include"]
|
37
|
+
begin
|
38
|
+
open(yaml["include"], "rb") do |u|
|
39
|
+
parse(u.read)
|
40
|
+
end
|
41
|
+
rescue OpenURI::HTTPError, Errno::ENOENT
|
42
|
+
raise HostFileError.new("Unable to include '#{yaml["include"]}'")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if yaml["hosts"]
|
47
|
+
if !@hosts
|
48
|
+
@hosts = yaml["hosts"]
|
49
|
+
else
|
50
|
+
yaml["hosts"].each do |key, value|
|
51
|
+
@hosts[key] = value
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
if yaml["lock_server_address"]
|
57
|
+
@lock_server_address = yaml["lock_server_address"]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def read
|
62
|
+
parse(File.read(config_file))
|
63
|
+
end
|
64
|
+
|
65
|
+
def hosts
|
66
|
+
@hosts.keys
|
67
|
+
end
|
68
|
+
|
69
|
+
def host(host_name)
|
70
|
+
@hosts[host_name]
|
71
|
+
end
|
72
|
+
|
73
|
+
def setup(url)
|
74
|
+
if File.exist?(config_file)
|
75
|
+
raise HostFileError.new("Config file '#{config_file}' already exists." +
|
76
|
+
" Canceling setup.")
|
77
|
+
end
|
78
|
+
|
79
|
+
FileUtils.mkdir_p(File.dirname(config_file))
|
80
|
+
File.open(config_file, "w") do |f|
|
81
|
+
f.puts("---")
|
82
|
+
f.puts("include: #{url}")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,133 @@
|
|
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 HostRunner < Runner
|
20
|
+
def initialize(host_name, host_config, username = "root")
|
21
|
+
@host_name = host_name
|
22
|
+
@username = username
|
23
|
+
config_file = host_config.config_file
|
24
|
+
|
25
|
+
host = host_config.host(host_name)
|
26
|
+
if !host
|
27
|
+
raise InvalidHostError.new("Host '#{host_name}' is not defined in '#{config_file}'")
|
28
|
+
end
|
29
|
+
|
30
|
+
@ip = host["address"]
|
31
|
+
@base_snapshot_id = host["base_snapshot_id"]
|
32
|
+
if !@ip
|
33
|
+
raise InvalidHostError.new(
|
34
|
+
"Missing 'address' field for host '#{host_name}' in '#{config_file}'"
|
35
|
+
)
|
36
|
+
end
|
37
|
+
if should_cleanup && !@base_snapshot_id
|
38
|
+
raise InvalidHostError.new(
|
39
|
+
"Missing 'base_snapshot_id' field for host '#{host_name}' in '#{config_file}'"
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
@command_runner = RemoteCommandRunner.new(@ip, @username)
|
44
|
+
@locker = LockService.new(host_config.lock_server_address)
|
45
|
+
end
|
46
|
+
|
47
|
+
def start
|
48
|
+
if !@locker.request_lock(@host_name)
|
49
|
+
raise LockError.new("Host '#{@host_name}' already locked")
|
50
|
+
end
|
51
|
+
|
52
|
+
connect
|
53
|
+
|
54
|
+
if should_cleanup
|
55
|
+
check_cleanup_capabilities
|
56
|
+
install_cleanup_interrupt_handler
|
57
|
+
end
|
58
|
+
|
59
|
+
@ip
|
60
|
+
end
|
61
|
+
|
62
|
+
def cleanup
|
63
|
+
return if @cleaned_up || !@connected
|
64
|
+
|
65
|
+
remote = RemoteCommandRunner.new(@ip, @username)
|
66
|
+
remote.run "snapper", "create", "-c", "number", "--pre-number", @base_snapshot_id.to_s,
|
67
|
+
"--description", "pennyworth_snapshot"
|
68
|
+
remote.run "snapper", "cleanup", "number"
|
69
|
+
remote.run "snapper", "undochange", "#{@base_snapshot_id}..0"
|
70
|
+
remote.run "bash", "-c", "reboot &"
|
71
|
+
@cleaned_up = true
|
72
|
+
end
|
73
|
+
|
74
|
+
def stop
|
75
|
+
if should_cleanup
|
76
|
+
cleanup
|
77
|
+
uninstall_cleanup_interrupt_handler
|
78
|
+
end
|
79
|
+
|
80
|
+
@locker.release_lock(@host_name)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# Makes sure the we can connect to the remote system as root (without a
|
86
|
+
# password or passphrase)
|
87
|
+
def connect
|
88
|
+
Cheetah.run "ssh", "-q", "-o", "BatchMode=yes", "root@#{@ip}"
|
89
|
+
rescue Cheetah::ExecutionFailed
|
90
|
+
raise SshConnectionFailed.new(
|
91
|
+
"Could not establish SSH connection to host '#{@ip}'. Please make sure that " \
|
92
|
+
"you can connect non-interactively as root, e.g. using ssh-agent.\n\n" \
|
93
|
+
"To copy your default ssh key to the machine run:\n" \
|
94
|
+
"ssh-copy-id root@#{@ip}"
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
def check_cleanup_capabilities
|
99
|
+
begin
|
100
|
+
RemoteCommandRunner.new(@ip, @username).run "snapper", "--help"
|
101
|
+
rescue Cheetah::ExecutionFailed
|
102
|
+
raise CommandNotFoundError.new(
|
103
|
+
"Snapper needs to be installed on the test system '#{@ip}' for the automatic cleanup."
|
104
|
+
)
|
105
|
+
end
|
106
|
+
@connected = true
|
107
|
+
end
|
108
|
+
|
109
|
+
def should_cleanup
|
110
|
+
!ENV["SKIP_HOST_CLEANUP"]
|
111
|
+
end
|
112
|
+
|
113
|
+
def install_cleanup_interrupt_handler
|
114
|
+
@old_interrupt_handler = trap("INT") do
|
115
|
+
trap("INT") do
|
116
|
+
exit!(1)
|
117
|
+
end
|
118
|
+
|
119
|
+
puts "RSpec is shutting down. Resetting test host '#{@ip}'." \
|
120
|
+
"Interrupt again to force exit."
|
121
|
+
cleanup
|
122
|
+
puts "Done."
|
123
|
+
|
124
|
+
@old_interrupt_handler.call
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def uninstall_cleanup_interrupt_handler
|
129
|
+
# Restore old interrupt handler
|
130
|
+
trap("INT", @old_interrupt_handler) if defined?(@old_interrupt_handler)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,89 @@
|
|
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 ImageRunner < Runner
|
20
|
+
DOMAIN_TEMPLATE = File.join(File.dirname(__FILE__) + "/../../files/image_test-template.xml")
|
21
|
+
|
22
|
+
attr_accessor :name
|
23
|
+
|
24
|
+
def initialize(image, username)
|
25
|
+
@image = image
|
26
|
+
@name = File.basename(image)
|
27
|
+
@username = username
|
28
|
+
|
29
|
+
@connection = ::Libvirt::open("qemu:///system")
|
30
|
+
end
|
31
|
+
|
32
|
+
def start
|
33
|
+
cleanup
|
34
|
+
|
35
|
+
ip = start_built_image
|
36
|
+
@command_runner = RemoteCommandRunner.new(ip, @username)
|
37
|
+
|
38
|
+
ip
|
39
|
+
end
|
40
|
+
|
41
|
+
def stop
|
42
|
+
system = @connection.lookup_domain_by_name(@name)
|
43
|
+
system.destroy
|
44
|
+
end
|
45
|
+
|
46
|
+
def cleanup_directory(_dir)
|
47
|
+
# The machine will be reset anyway after the tests, so this is is a NOP
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def cleanup
|
53
|
+
system = @connection.lookup_domain_by_name(@name)
|
54
|
+
system.destroy
|
55
|
+
rescue
|
56
|
+
end
|
57
|
+
|
58
|
+
# Creates a transient kvm domain from the predefined image_test-domain.xml
|
59
|
+
# file and returns the ip address for further interaction.
|
60
|
+
def start_built_image
|
61
|
+
domain_config = File.read(DOMAIN_TEMPLATE)
|
62
|
+
domain_config.gsub!("@@image@@", @image)
|
63
|
+
domain_config.gsub!("@@name@@", @name)
|
64
|
+
|
65
|
+
@connection.create_domain_xml(domain_config)
|
66
|
+
system = @connection.lookup_domain_by_name(@name)
|
67
|
+
|
68
|
+
domain_xml = Nokogiri::XML(system.xml_desc)
|
69
|
+
mac = domain_xml.xpath("//domain/devices/interface/mac").attr("address")
|
70
|
+
ip_address = nil
|
71
|
+
|
72
|
+
# Loop until the VM has got an IP address we can return
|
73
|
+
lease_file = "/var/lib/libvirt/dnsmasq/default.leases"
|
74
|
+
300.times do
|
75
|
+
match = File.readlines(lease_file).grep(/#{mac}/).first
|
76
|
+
if match
|
77
|
+
ip_address = match.split[2]
|
78
|
+
break
|
79
|
+
end
|
80
|
+
|
81
|
+
sleep 1
|
82
|
+
end
|
83
|
+
|
84
|
+
ip_address
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,93 @@
|
|
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 Libvirt
|
20
|
+
LIBVIRT_NET_NAME = "default"
|
21
|
+
LIBVIRT_POOL_NAME = "default"
|
22
|
+
|
23
|
+
class << self
|
24
|
+
def ensure_libvirt_env_started
|
25
|
+
# The check here is unnecessary for technical reasons ("sysctl start" does
|
26
|
+
# not fail if the service is already running), but it avoids an unnecessary
|
27
|
+
# sudo password prompt.
|
28
|
+
libvirtd_start unless libvirtd_active?
|
29
|
+
|
30
|
+
libvirt_net_start unless libvirt_net_active?
|
31
|
+
|
32
|
+
# As default pool is not always available but gets sometimes created by
|
33
|
+
# tools like virt-manager, we need to create it ourself if it does not yet
|
34
|
+
# exist.
|
35
|
+
libvirt_pool_create unless libvirt_pool_exists?
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def libvirtd_start
|
41
|
+
Cheetah.run "sudo", "systemctl", "start", "libvirtd"
|
42
|
+
|
43
|
+
sleep 0.1 until File.exists?("/var/run/libvirt/libvirt-sock")
|
44
|
+
end
|
45
|
+
|
46
|
+
def libvirtd_active?
|
47
|
+
output = Cheetah.run "systemctl", "show", "--property", "ActiveState", "libvirtd", :stdout => :capture
|
48
|
+
|
49
|
+
output == "ActiveState=active"
|
50
|
+
end
|
51
|
+
|
52
|
+
def libvirt_net_start
|
53
|
+
Cheetah.run "virsh", "-c", "qemu:///system", "net-start", LIBVIRT_NET_NAME
|
54
|
+
end
|
55
|
+
|
56
|
+
def libvirt_net_active?
|
57
|
+
output = with_c_locale do
|
58
|
+
Cheetah.run "virsh", "-c", "qemu:///system", "net-list", "--all", :stdout => :capture
|
59
|
+
end
|
60
|
+
|
61
|
+
# The output looks like this:
|
62
|
+
#
|
63
|
+
# Name State Autostart Persistent
|
64
|
+
# ----------------------------------------------------------
|
65
|
+
# default active no yes
|
66
|
+
# vagrant0 active yes yes
|
67
|
+
#
|
68
|
+
output.split("\n")[2..-1].find do |line|
|
69
|
+
line =~ /^\s*#{LIBVIRT_NET_NAME}\s+active/
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def libvirt_pool_create
|
74
|
+
pool_config_file = File.dirname(__FILE__) + "/../../files/pool-default.xml"
|
75
|
+
Cheetah.run "virsh", "-c", "qemu:///system", "pool-create", pool_config_file
|
76
|
+
end
|
77
|
+
|
78
|
+
def libvirt_pool_exists?
|
79
|
+
output = with_c_locale do
|
80
|
+
Cheetah.run "virsh", "-c", "qemu:///system", "pool-list", "--all", :stdout => :capture
|
81
|
+
end
|
82
|
+
|
83
|
+
# The output looks like this:
|
84
|
+
#
|
85
|
+
# Name State Autostart
|
86
|
+
# -----------------------------------------
|
87
|
+
# default active no
|
88
|
+
#
|
89
|
+
output.split("\n")[2..-1].detect { |line| line =~ /^\s*#{LIBVIRT_POOL_NAME}/ }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,77 @@
|
|
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
|
+
# LocalCommandRunner is used for executing commands on the local machine
|
20
|
+
class LocalCommandRunner
|
21
|
+
# Initialize the command runner
|
22
|
+
#
|
23
|
+
# +opts+:: Options to modify how and which the commands are run.
|
24
|
+
#
|
25
|
+
# Available options:
|
26
|
+
# [env]:: Hash of environment options to set for the command, e.g.
|
27
|
+
# {
|
28
|
+
# "MACHINERY_DIR" => "/tmp/machinery"
|
29
|
+
# }
|
30
|
+
def initialize(opts = {})
|
31
|
+
@env = opts[:env] || {}
|
32
|
+
end
|
33
|
+
|
34
|
+
def run(*args)
|
35
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
36
|
+
|
37
|
+
with_env(@env) do
|
38
|
+
Cheetah.run(
|
39
|
+
"bash", "-c", *args, options
|
40
|
+
)
|
41
|
+
end
|
42
|
+
rescue Cheetah::ExecutionFailed => e
|
43
|
+
raise ExecutionFailed.new(e)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Copy a local file to the remote system.
|
47
|
+
#
|
48
|
+
# +source+:: Path to the local file
|
49
|
+
# +destination+:: Path to the remote file or directory. If +destination+ is a
|
50
|
+
# path, the same filename as +source+ will be used.
|
51
|
+
# +opts+:: Options to modify the attributes of the remote file.
|
52
|
+
#
|
53
|
+
# Available options:
|
54
|
+
# [owner]:: Owner of the file, e.g. "tux"
|
55
|
+
# [group]:: Group of the file, e.g. "users"
|
56
|
+
# [mode]:: Mode of the file, e.g. "600"
|
57
|
+
def inject_file(source, destination, opts = {})
|
58
|
+
# Append filename (taken from +source+) to destination if it is a path, so
|
59
|
+
# that +destination+ is always the full target path including the filename.
|
60
|
+
destination = File.join(destination, File.basename(source)) if File.directory?(destination)
|
61
|
+
|
62
|
+
FileUtils.cp(source, destination)
|
63
|
+
FileUtils.chown(opts[:owner], opts[:group], destination)
|
64
|
+
FileUtils.chmod(opts[:mode], destination) if opts[:mode]
|
65
|
+
end
|
66
|
+
|
67
|
+
def extract_file(source, destination)
|
68
|
+
FileUtils.cp(source, destination)
|
69
|
+
end
|
70
|
+
|
71
|
+
def inject_directory(source, destination, opts = {})
|
72
|
+
FileUtils.mkdir_p(destination)
|
73
|
+
FileUtils.cp_r(source, destination)
|
74
|
+
FileUtils.chown_R(opts[:owner], opts[:group], destination)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|