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.
- 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,34 @@
|
|
|
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 LocalRunner < Runner
|
|
20
|
+
def initialize(opts = {})
|
|
21
|
+
@command_runner = LocalCommandRunner.new(opts)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def start
|
|
25
|
+
# Nothing to do here
|
|
26
|
+
|
|
27
|
+
"127.0.0.1"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def stop
|
|
31
|
+
# Nothing to do here either
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Copyright (c) 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 LockService
|
|
20
|
+
attr_reader :lock_server_host
|
|
21
|
+
attr_reader :lock_server_port
|
|
22
|
+
|
|
23
|
+
def initialize(lock_server_address)
|
|
24
|
+
fields = lock_server_address.split(":")
|
|
25
|
+
@lock_server_host = fields[0]
|
|
26
|
+
@lock_server_port = fields[1]
|
|
27
|
+
@sockets = {}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def socket(lock_name)
|
|
31
|
+
if !@sockets.has_key?(lock_name)
|
|
32
|
+
@sockets[lock_name] = TCPSocket.new(@lock_server_host, @lock_server_port)
|
|
33
|
+
end
|
|
34
|
+
@sockets[lock_name]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def request_lock(lock_name)
|
|
38
|
+
socket(lock_name).puts("g #{lock_name}")
|
|
39
|
+
response = socket(lock_name).gets
|
|
40
|
+
if response =~ /^1/
|
|
41
|
+
return true
|
|
42
|
+
elsif response =~ /^0/
|
|
43
|
+
return false
|
|
44
|
+
else
|
|
45
|
+
raise LockError.new("Error, received: #{response}")
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def keep_lock
|
|
50
|
+
# Sleep forever to keep process running to keep TCP connection to lock
|
|
51
|
+
# server open. When the process is ended the connection is closed and the
|
|
52
|
+
# lock is released. Users can end the process and release the lock with
|
|
53
|
+
# Ctrl-C.
|
|
54
|
+
sleep
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def release_lock(lock_name)
|
|
58
|
+
if !@sockets[lock_name]
|
|
59
|
+
raise LockError.new("Lock '#{lock_name}' doesn't exist")
|
|
60
|
+
end
|
|
61
|
+
@sockets[lock_name].close
|
|
62
|
+
@sockets.delete(lock_name)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def locked?(lock_name)
|
|
66
|
+
socket(lock_name).puts("i #{lock_name}")
|
|
67
|
+
response = socket(lock_name).gets
|
|
68
|
+
if response =~ /^1/
|
|
69
|
+
return true
|
|
70
|
+
else
|
|
71
|
+
return false
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def info(lock_name)
|
|
76
|
+
if locked?(lock_name)
|
|
77
|
+
socket(lock_name).puts("d #{lock_name}")
|
|
78
|
+
response = socket(lock_name).gets
|
|
79
|
+
response =~ /^#{lock_name}: (.*):/
|
|
80
|
+
client = $1
|
|
81
|
+
return "'#{lock_name}' is locked by #{client}"
|
|
82
|
+
else
|
|
83
|
+
return "'#{lock_name}' is not locked"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
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
|
+
# The purpose of this class is to execute commands on a remote machine via SSH.
|
|
19
|
+
module Pennyworth
|
|
20
|
+
class RemoteCommandRunner
|
|
21
|
+
def initialize(ip, username)
|
|
22
|
+
@ip = ip
|
|
23
|
+
@username = username
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def run(*args)
|
|
27
|
+
# When ssh executes commands, it passes them through shell expansion.
|
|
28
|
+
# For example, compare
|
|
29
|
+
#
|
|
30
|
+
# $ echo '$HOME'
|
|
31
|
+
# $HOME
|
|
32
|
+
#
|
|
33
|
+
# with
|
|
34
|
+
#
|
|
35
|
+
# $ ssh localhost echo '$HOME'
|
|
36
|
+
# /home/dmajda
|
|
37
|
+
#
|
|
38
|
+
# To mitigate that and maintain usual Cheetah semantics, we need to
|
|
39
|
+
# protect the command and its arguments using another layer of escaping.
|
|
40
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
|
41
|
+
args.map! { |a| Shellwords.escape(a) } if !options[:skip_escape]
|
|
42
|
+
|
|
43
|
+
if user = options.delete(:as)
|
|
44
|
+
args = ["su", "-l", user, "-c"] + args
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
Cheetah.run(
|
|
48
|
+
"ssh",
|
|
49
|
+
"-o",
|
|
50
|
+
"UserKnownHostsFile=/dev/null",
|
|
51
|
+
"-o",
|
|
52
|
+
"StrictHostKeyChecking=no",
|
|
53
|
+
"#{@username}@#{@ip}",
|
|
54
|
+
"LC_ALL=C",
|
|
55
|
+
*args,
|
|
56
|
+
options
|
|
57
|
+
)
|
|
58
|
+
rescue Cheetah::ExecutionFailed => e
|
|
59
|
+
raise ExecutionFailed.new(e)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Copy a local file to the remote system.
|
|
63
|
+
#
|
|
64
|
+
# +source+:: Path to the local file
|
|
65
|
+
# +destination+:: Path to the remote file or directory. If +destination+ is a
|
|
66
|
+
# path, the same filename as +source+ will be used.
|
|
67
|
+
# +opts+:: Options to modify the attributes of the remote file.
|
|
68
|
+
#
|
|
69
|
+
# Available options:
|
|
70
|
+
# [owner]:: Owner of the file, e.g. "tux"
|
|
71
|
+
# [group]:: Group of the file, e.g. "users"
|
|
72
|
+
# [mode]:: Mode of the file, e.g. "600"
|
|
73
|
+
def inject_file(source, destination, opts = {})
|
|
74
|
+
# Append filename (taken from +source+) to destination if it is a path, so
|
|
75
|
+
# that +destination+ is always the full target path including the filename.
|
|
76
|
+
destination += File.basename(source) if destination.end_with?("/")
|
|
77
|
+
|
|
78
|
+
Cheetah.run(
|
|
79
|
+
"scp",
|
|
80
|
+
"-o",
|
|
81
|
+
"UserKnownHostsFile=/dev/null",
|
|
82
|
+
"-o",
|
|
83
|
+
"StrictHostKeyChecking=no",
|
|
84
|
+
source,
|
|
85
|
+
"#{@username}@#{@ip}:#{destination}"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
if opts[:owner] || opts[:group]
|
|
89
|
+
owner_group = opts[:owner] || ""
|
|
90
|
+
owner_group += ":#{opts[:group]}" if opts[:group]
|
|
91
|
+
run "chown", "-R", owner_group, destination
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
if opts[:mode]
|
|
95
|
+
run "chmod", opts[:mode], destination
|
|
96
|
+
end
|
|
97
|
+
rescue Cheetah::ExecutionFailed => e
|
|
98
|
+
raise ExecutionFailed.new(e)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def extract_file(source, destination)
|
|
102
|
+
Cheetah.run(
|
|
103
|
+
"scp",
|
|
104
|
+
"-o",
|
|
105
|
+
"UserKnownHostsFile=/dev/null",
|
|
106
|
+
"-o",
|
|
107
|
+
"StrictHostKeyChecking=no",
|
|
108
|
+
"#{@username}@#{@ip}:#{source}",
|
|
109
|
+
destination
|
|
110
|
+
)
|
|
111
|
+
rescue Cheetah::ExecutionFailed => e
|
|
112
|
+
raise ExecutionFailed.new(e)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def inject_directory(source, destination, opts = {})
|
|
116
|
+
if opts[:owner] || opts[:group]
|
|
117
|
+
owner_group = opts[:owner] || ""
|
|
118
|
+
owner_group += ":#{opts[:group]}" if opts[:group]
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
chown_cmd = " && chown #{owner_group} '#{destination}'" if owner_group
|
|
122
|
+
mkdir_cmd = "test -d '#{destination}' || (mkdir -p '#{destination}' #{chown_cmd} )"
|
|
123
|
+
|
|
124
|
+
run mkdir_cmd, skip_escape: true
|
|
125
|
+
|
|
126
|
+
Cheetah.run(
|
|
127
|
+
"scp",
|
|
128
|
+
"-r",
|
|
129
|
+
"-o",
|
|
130
|
+
"UserKnownHostsFile=/dev/null",
|
|
131
|
+
"-o",
|
|
132
|
+
"StrictHostKeyChecking=no",
|
|
133
|
+
source,
|
|
134
|
+
"#{@username}@#{@ip}:#{destination}"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
if owner_group
|
|
138
|
+
run "chown", "-R", owner_group, File.join(destination, File.basename(source))
|
|
139
|
+
end
|
|
140
|
+
rescue Cheetah::ExecutionFailed => e
|
|
141
|
+
raise ExecutionFailed.new(e)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
# Base class for the runner classes
|
|
20
|
+
class Runner
|
|
21
|
+
attr_reader :command_runner
|
|
22
|
+
|
|
23
|
+
def cleanup_directory(dir)
|
|
24
|
+
command_runner.run("test -d #{dir} && rm -r #{dir}")
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
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 Settings
|
|
20
|
+
|
|
21
|
+
attr_accessor :verbose, :silent, :definitions_dir
|
|
22
|
+
|
|
23
|
+
def initialize
|
|
24
|
+
@verbose = false
|
|
25
|
+
@silent = false
|
|
26
|
+
@definitions_dir = File.expand_path("~/.pennyworth")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def kiwi_dir
|
|
30
|
+
File.join(@definitions_dir, "/kiwi")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def vagrant_dir
|
|
34
|
+
File.join(@definitions_dir, "/vagrant")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def version
|
|
38
|
+
Pennyworth::VERSION
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
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
|
+
require "cheetah"
|
|
19
|
+
require "libvirt"
|
|
20
|
+
require "socket"
|
|
21
|
+
require "open-uri"
|
|
22
|
+
require "yaml"
|
|
23
|
+
|
|
24
|
+
require_relative "exceptions"
|
|
25
|
+
require_relative "helper"
|
|
26
|
+
require_relative "libvirt"
|
|
27
|
+
require_relative "runner"
|
|
28
|
+
require_relative "vagrant"
|
|
29
|
+
require_relative "vagrant_runner"
|
|
30
|
+
require_relative "image_runner"
|
|
31
|
+
require_relative "host_config"
|
|
32
|
+
require_relative "host_runner"
|
|
33
|
+
require_relative "lock_service"
|
|
34
|
+
require_relative "ssh_keys_importer"
|
|
35
|
+
require_relative "vm"
|
|
36
|
+
require_relative "spec_profiler"
|
|
37
|
+
require_relative "remote_command_runner"
|
|
38
|
+
require_relative "settings"
|
|
39
|
+
require_relative "local_runner"
|
|
40
|
+
require_relative "local_command_runner"
|
|
41
|
+
|
|
42
|
+
module Pennyworth
|
|
43
|
+
module SpecHelper
|
|
44
|
+
def start_system(opts)
|
|
45
|
+
opts = {
|
|
46
|
+
skip_ssh_setup: false
|
|
47
|
+
}.merge(opts)
|
|
48
|
+
username = opts[:username] || "root"
|
|
49
|
+
if opts[:box]
|
|
50
|
+
runner = VagrantRunner.new(opts[:box], RSpec.configuration.vagrant_dir, username)
|
|
51
|
+
password = opts[:password] || "vagrant"
|
|
52
|
+
elsif opts[:image]
|
|
53
|
+
runner = ImageRunner.new(opts[:image], username)
|
|
54
|
+
password = opts[:password] || "linux"
|
|
55
|
+
elsif opts[:host]
|
|
56
|
+
config = HostConfig.new(RSpec.configuration.hosts_file)
|
|
57
|
+
config.read
|
|
58
|
+
runner = HostRunner.new(opts[:host], config, username)
|
|
59
|
+
elsif opts[:local]
|
|
60
|
+
runner = LocalRunner.new(env: opts[:env])
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
raise "No image specified." unless runner
|
|
64
|
+
|
|
65
|
+
system = VM.new(runner)
|
|
66
|
+
|
|
67
|
+
# Make sure to stop the machine again when the example group is done
|
|
68
|
+
self.class.after(:all) do
|
|
69
|
+
system.stop
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
measure("Boot machine '#{opts[:box] || opts[:image] || opts[:host]}'") do
|
|
73
|
+
system.start
|
|
74
|
+
end
|
|
75
|
+
if !opts[:skip_ssh_setup] && !opts[:host] && !opts[:local]
|
|
76
|
+
SshKeysImporter.import(system.ip, username, password)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
system
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
RSpec.configure do |config|
|
|
85
|
+
defaults = Pennyworth::Settings.new
|
|
86
|
+
config.include(Pennyworth::SpecHelper)
|
|
87
|
+
config.add_setting :pennyworth_mode, default: false
|
|
88
|
+
config.add_setting :vagrant_dir, default: defaults.vagrant_dir
|
|
89
|
+
config.add_setting :hosts_file, default: File.join(defaults.definitions_dir, "/hosts.yaml")
|
|
90
|
+
|
|
91
|
+
config.before(:all) do
|
|
92
|
+
unless RSpec.configuration.pennyworth_mode
|
|
93
|
+
Pennyworth::Libvirt.ensure_libvirt_env_started
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
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
|
+
require "benchmark"
|
|
19
|
+
|
|
20
|
+
def measure(label, &block)
|
|
21
|
+
own_parent = @parent_measurement
|
|
22
|
+
measurement = {
|
|
23
|
+
label: label,
|
|
24
|
+
child_measurements: []
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@parent_measurement = measurement
|
|
28
|
+
time = Benchmark.measure do
|
|
29
|
+
block.call
|
|
30
|
+
end
|
|
31
|
+
@parent_measurement = own_parent
|
|
32
|
+
measurement.merge!(time: time.real)
|
|
33
|
+
|
|
34
|
+
# Calculate time that was not spent in the measured child blocks but somewhere
|
|
35
|
+
# else
|
|
36
|
+
if !measurement[:child_measurements].empty?
|
|
37
|
+
other_time = measurement[:time]
|
|
38
|
+
measurement[:child_measurements].each do |child|
|
|
39
|
+
other_time -= child[:time]
|
|
40
|
+
end
|
|
41
|
+
measurement[:child_measurements] << { label: "Other", time: other_time }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
if own_parent
|
|
45
|
+
own_parent[:child_measurements] << measurement
|
|
46
|
+
else
|
|
47
|
+
@measurements << measurement
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def print_measurement(measurement, indent = 0)
|
|
52
|
+
name = measurement[:label][0..65-indent].ljust(70-indent)
|
|
53
|
+
STDERR.puts (" " * indent) + "#{name}: #{measurement[:time]}"
|
|
54
|
+
|
|
55
|
+
if measurement[:child_measurements]
|
|
56
|
+
measurement[:child_measurements].each do |child|
|
|
57
|
+
print_measurement(child, indent + 2)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
RSpec.configure do |config|
|
|
63
|
+
config.before(:all) do
|
|
64
|
+
@measurements = []
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
config.around(:each) do |example|
|
|
68
|
+
if RSpec.configuration.pennyworth_mode
|
|
69
|
+
example.run
|
|
70
|
+
else
|
|
71
|
+
measure(example.metadata[:full_description]) do
|
|
72
|
+
example.run
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
config.after(:all) do
|
|
78
|
+
if !RSpec.configuration.pennyworth_mode
|
|
79
|
+
@measurements.each do |measurement|
|
|
80
|
+
print_measurement(measurement)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|