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
data/examples/README.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Pennyworth Examples
|
2
|
+
|
3
|
+
This directory contains an example base image definition and Vagrantfile in
|
4
|
+
order to demonstrate how a testing environment can be defined using pennyworth.
|
5
|
+
It provides a very basic openSUSE 13.1 machine.
|
6
|
+
|
7
|
+
## Base Image
|
8
|
+
|
9
|
+
The base image is defined in `examples/kiwi/definitions/base_opensuse13.1_kvm`.
|
10
|
+
It can be build with:
|
11
|
+
|
12
|
+
`$ bin/pennyworth -d examples/ build-base`
|
13
|
+
|
14
|
+
You can then import the resulting image into vagrant:
|
15
|
+
|
16
|
+
`$ bin/pennyworth -d examples/ import-base`
|
17
|
+
|
18
|
+
## VM
|
19
|
+
|
20
|
+
At that point the 13.1 machine is ready to be used and can be started up like
|
21
|
+
this:
|
22
|
+
|
23
|
+
`$ bin/pennyworth -d examples/ up opensuse131`
|
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
#======================================
|
3
|
+
# Functions...
|
4
|
+
#--------------------------------------
|
5
|
+
test -f /.kconfig && . /.kconfig
|
6
|
+
test -f /.profile && . /.profile
|
7
|
+
|
8
|
+
#======================================
|
9
|
+
# Greeting...
|
10
|
+
#--------------------------------------
|
11
|
+
echo "Configure image: [$kiwi_iname]..."
|
12
|
+
|
13
|
+
#======================================
|
14
|
+
# Mount system filesystems
|
15
|
+
#--------------------------------------
|
16
|
+
baseMount
|
17
|
+
|
18
|
+
#======================================
|
19
|
+
# Setup baseproduct link
|
20
|
+
#--------------------------------------
|
21
|
+
suseSetupProduct
|
22
|
+
|
23
|
+
#======================================
|
24
|
+
# Add missing gpg keys to rpm
|
25
|
+
#--------------------------------------
|
26
|
+
suseImportBuildKey
|
27
|
+
|
28
|
+
#======================================
|
29
|
+
# Activate services
|
30
|
+
#--------------------------------------
|
31
|
+
suseInsertService sshd
|
32
|
+
|
33
|
+
#======================================
|
34
|
+
# Setup default target, multi-user
|
35
|
+
#--------------------------------------
|
36
|
+
baseSetRunlevel 3
|
37
|
+
|
38
|
+
#======================================
|
39
|
+
# SuSEconfig
|
40
|
+
#--------------------------------------
|
41
|
+
suseConfig
|
42
|
+
|
43
|
+
#======================================
|
44
|
+
# Vagrant
|
45
|
+
#--------------------------------------
|
46
|
+
date > /etc/vagrant_box_build_time
|
47
|
+
# set vagrant sudo
|
48
|
+
printf "%b" "
|
49
|
+
# added by veewee/postinstall.sh
|
50
|
+
vagrant ALL=(ALL) NOPASSWD: ALL
|
51
|
+
" >> /etc/sudoers
|
52
|
+
|
53
|
+
# speed-up remote logins
|
54
|
+
printf "%b" "
|
55
|
+
# added by veewee/postinstall.sh
|
56
|
+
UseDNS no
|
57
|
+
" >> /etc/ssh/sshd_config
|
58
|
+
|
59
|
+
#======================================
|
60
|
+
# Fixes for base images
|
61
|
+
#--------------------------------------
|
62
|
+
|
63
|
+
echo 'solver.allowVendorChange = true' >> /etc/zypp/zypp.conf
|
64
|
+
echo 'solver.onlyRequires = true' >> /etc/zypp/zypp.conf
|
65
|
+
|
66
|
+
# remove non-static files which break the tests on rebuilds
|
67
|
+
rm /var/log/YaST2/config_diff_*.log
|
68
|
+
rm /etc/zypp/repos.d/dir-*.repo
|
69
|
+
|
70
|
+
# avoid mac address configured into system, this results in getting
|
71
|
+
# eth1 instead of eth0 in virtualized environments sometimes
|
72
|
+
rm -f /etc/udev/rules.d/70-persistent-net.rules
|
73
|
+
|
74
|
+
# Disable cron jobs in order to prevent created files breaking the tests
|
75
|
+
rm /etc/cron.daily/*
|
76
|
+
|
77
|
+
#======================================
|
78
|
+
# Repositories
|
79
|
+
#--------------------------------------
|
80
|
+
zypper --gpg-auto-import-keys ar --refresh --name "Main Repository (OSS)" http://download.opensuse.org/distribution/13.1/repo/oss/ download.opensuse.org-oss
|
81
|
+
|
82
|
+
#======================================
|
83
|
+
# Umount kernel filesystems
|
84
|
+
#--------------------------------------
|
85
|
+
baseCleanMount
|
86
|
+
|
87
|
+
exit 0
|
@@ -0,0 +1,64 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
|
3
|
+
<image schemaversion="6.1" name="Base-openSUSE-13.1">
|
4
|
+
<description type="system">
|
5
|
+
<author>Machinery-Team</author>
|
6
|
+
<contact>machinery@lists.suse.com</contact>
|
7
|
+
<specification>
|
8
|
+
Base openSUSE 13.1 box
|
9
|
+
</specification>
|
10
|
+
</description>
|
11
|
+
<preferences>
|
12
|
+
<type image="vmx" filesystem="ext4" boot="vmxboot/suse-13.1" format="vagrant" bootloader="grub2" kernelcmdline="root=/dev/vda1 disk=/dev/vda nomodeset LOCAL_BOOT=yes">
|
13
|
+
<vagrantconfig provider="libvirt" virtualsize="16"/>
|
14
|
+
<size unit="G">15</size>
|
15
|
+
</type>
|
16
|
+
<version>1.13.1</version>
|
17
|
+
<packagemanager>zypper</packagemanager>
|
18
|
+
<locale>en_US</locale>
|
19
|
+
<keytable>us.map.gz</keytable>
|
20
|
+
<timezone>Europe/Berlin</timezone>
|
21
|
+
<hwclock>utc</hwclock>
|
22
|
+
<rpm-excludedocs>true</rpm-excludedocs>
|
23
|
+
</preferences>
|
24
|
+
<users group="root">
|
25
|
+
<user name="root" password="vagrant" pwdformat="plain" home="/root"/>
|
26
|
+
</users>
|
27
|
+
<users group="vagrant">
|
28
|
+
<user name="vagrant" password="vagrant" pwdformat="plain" home="/home/vagrant"/>
|
29
|
+
</users>
|
30
|
+
<repository type="yast2">
|
31
|
+
<source path="obs://13.1/repo/oss"/>
|
32
|
+
</repository>
|
33
|
+
<packages type="image">
|
34
|
+
<namedCollection name="base"/>
|
35
|
+
<product name="openSUSE"/>
|
36
|
+
<package name="ifplugd"/>
|
37
|
+
<package name="iputils"/>
|
38
|
+
<package name="vim"/>
|
39
|
+
<package name="grub2"/>
|
40
|
+
<package name="syslinux"/>
|
41
|
+
<package name="lvm2"/>
|
42
|
+
<package name="tar"/>
|
43
|
+
<package name="parted"/>
|
44
|
+
<package name="sudo"/>
|
45
|
+
<package name="rsync"/>
|
46
|
+
<package name="kernel-default"/>
|
47
|
+
<package name="squashfs"/>
|
48
|
+
<package name="iproute2"/>
|
49
|
+
<package name="cronie"/>
|
50
|
+
<package name="nfs-kernel-server"/>
|
51
|
+
<package name="autofs"/>
|
52
|
+
</packages>
|
53
|
+
<packages type="bootstrap">
|
54
|
+
<package name="udev"/>
|
55
|
+
<package name="filesystem"/>
|
56
|
+
<package name="glibc-locale"/>
|
57
|
+
<package name="cracklib-dict-full"/>
|
58
|
+
<package name="ca-certificates"/>
|
59
|
+
<package name="module-init-tools"/>
|
60
|
+
</packages>
|
61
|
+
<packages type="delete">
|
62
|
+
<package name="kernel-debug"/>
|
63
|
+
</packages>
|
64
|
+
</image>
|
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key
|
@@ -0,0 +1,14 @@
|
|
1
|
+
VAGRANTFILE_API_VERSION = "2"
|
2
|
+
|
3
|
+
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
4
|
+
config.vm.define :opensuse131 do |opensuse131|
|
5
|
+
opensuse131.vm.box = "base_opensuse13.1_kvm"
|
6
|
+
|
7
|
+
opensuse131.vm.provider :libvirt do |domain|
|
8
|
+
domain.memory = 1024
|
9
|
+
domain.cpus = 1
|
10
|
+
domain.nested = false
|
11
|
+
domain.volume_cache = 'none'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
<domain type='kvm'>
|
2
|
+
<name>@@name@@</name>
|
3
|
+
<!-- <uuid>#{UUID}</uuid> -->
|
4
|
+
<memory>1048576</memory>
|
5
|
+
<currentMemory>1048576</currentMemory>
|
6
|
+
<vcpu>1</vcpu>
|
7
|
+
<os>
|
8
|
+
<type arch='x86_64'>hvm</type>
|
9
|
+
<boot dev='hd'/>
|
10
|
+
</os>
|
11
|
+
<features>
|
12
|
+
<acpi/>
|
13
|
+
<apic/>
|
14
|
+
<pae/>
|
15
|
+
</features>
|
16
|
+
<clock offset='utc'/>
|
17
|
+
<on_poweroff>destroy</on_poweroff>
|
18
|
+
<on_reboot>restart</on_reboot>
|
19
|
+
<on_crash>restart</on_crash>
|
20
|
+
<devices>
|
21
|
+
<disk type='file' device='disk'>
|
22
|
+
<driver name='qemu' type='qcow2'/>
|
23
|
+
<source file='@@image@@'/>
|
24
|
+
<target dev='vda' bus='virtio'/>
|
25
|
+
</disk>
|
26
|
+
<interface type='network'>
|
27
|
+
<model type='virtio'/>
|
28
|
+
<source network='default'/>
|
29
|
+
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
|
30
|
+
</interface>
|
31
|
+
<serial type='pty'>
|
32
|
+
<target port='0'/>
|
33
|
+
</serial>
|
34
|
+
<console type='pty'>
|
35
|
+
<target port='0'/>
|
36
|
+
</console>
|
37
|
+
<input type='mouse' bus='ps2'/>
|
38
|
+
<graphics type='vnc' port='-1' autoport='yes' keymap='en-us'/>
|
39
|
+
<video>
|
40
|
+
<model type='cirrus' vram='9216' heads='1'/>
|
41
|
+
</video>
|
42
|
+
</devices>
|
43
|
+
</domain>
|
data/lib/image_runner.rb
ADDED
@@ -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
|
data/lib/pennyworth.rb
ADDED
@@ -0,0 +1,65 @@
|
|
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 "rubygems"
|
19
|
+
|
20
|
+
require "gli"
|
21
|
+
require "cheetah"
|
22
|
+
require "yaml"
|
23
|
+
require "colorize"
|
24
|
+
require "libvirt"
|
25
|
+
require "nokogiri"
|
26
|
+
require "digest"
|
27
|
+
require "net/http"
|
28
|
+
require "find"
|
29
|
+
require "open-uri"
|
30
|
+
|
31
|
+
module Pennyworth
|
32
|
+
end
|
33
|
+
|
34
|
+
require_relative "pennyworth/version"
|
35
|
+
require_relative "pennyworth/exceptions"
|
36
|
+
require_relative "pennyworth/cli"
|
37
|
+
require_relative "pennyworth/helper"
|
38
|
+
require_relative "pennyworth/vagrant"
|
39
|
+
require_relative "pennyworth/commands/command"
|
40
|
+
require_relative "pennyworth/commands/setup_command"
|
41
|
+
require_relative "pennyworth/commands/status_command"
|
42
|
+
require_relative "pennyworth/commands/base_command"
|
43
|
+
require_relative "pennyworth/commands/build_base_command"
|
44
|
+
require_relative "pennyworth/commands/import_base_command"
|
45
|
+
require_relative "pennyworth/commands/up_command"
|
46
|
+
require_relative "pennyworth/commands/down_command"
|
47
|
+
require_relative "pennyworth/commands/boot_command"
|
48
|
+
require_relative "pennyworth/commands/shutdown_command"
|
49
|
+
require_relative "pennyworth/commands/import_ssh_keys_command"
|
50
|
+
require_relative "pennyworth/commands/list_command"
|
51
|
+
require_relative "pennyworth/vagrant_command"
|
52
|
+
require_relative "pennyworth/settings"
|
53
|
+
require_relative "pennyworth/runner"
|
54
|
+
require_relative "pennyworth/image_runner"
|
55
|
+
require_relative "pennyworth/vm"
|
56
|
+
require_relative "pennyworth/libvirt"
|
57
|
+
require_relative "pennyworth/ssh_keys_importer"
|
58
|
+
require_relative "pennyworth/urls"
|
59
|
+
require_relative "pennyworth/host_runner"
|
60
|
+
require_relative "pennyworth/cli_host_controller"
|
61
|
+
require_relative "pennyworth/host_config"
|
62
|
+
require_relative "pennyworth/lock_service"
|
63
|
+
require_relative "pennyworth/remote_command_runner"
|
64
|
+
require_relative "pennyworth/local_runner"
|
65
|
+
require_relative "pennyworth/local_command_runner"
|
@@ -0,0 +1,339 @@
|
|
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 Cli
|
20
|
+
extend GLI::App
|
21
|
+
|
22
|
+
program_desc 'A tool for controlling networks of machines for integration testing'
|
23
|
+
program_long_desc <<-LONGDESC
|
24
|
+
Pennyworth is a tool for controlling a network of machines for
|
25
|
+
integration testing. It helps to control virtual and real machines to
|
26
|
+
provide a well-defined test environment for automated tests.
|
27
|
+
|
28
|
+
Use the global `--definitions-dir` option to specify the path to the
|
29
|
+
directory containing Kiwi and Vagrant definitions. The directory needs to
|
30
|
+
contain `kiwi/` and `vagrant/` subdirectories. Default is `~/.pennyworth`.
|
31
|
+
|
32
|
+
Pennyworth writes a log file to `/tmp/pennyworth.log`.
|
33
|
+
|
34
|
+
Use the `help` command to get documentation about the individual commands.
|
35
|
+
Find more documentation at https://github.com/SUSE/pennyworth.
|
36
|
+
LONGDESC
|
37
|
+
|
38
|
+
preserve_argv(true)
|
39
|
+
@version = Pennyworth::VERSION
|
40
|
+
switch :version, :negatable => false, :desc => "Show version"
|
41
|
+
switch [:help, :h], :negatable => false, :desc => "Show help"
|
42
|
+
switch :verbose, :negatable => false, :desc => "Verbose"
|
43
|
+
switch [:silent], :negatable => false, :desc => "Silent mode"
|
44
|
+
flag ["definitions-dir", :d],
|
45
|
+
:desc => "Path to the directory containing machine definitions",
|
46
|
+
:arg_name => "DEFINITIONS_DIR"
|
47
|
+
|
48
|
+
pre do |global_options,command,options,args|
|
49
|
+
@@settings.verbose = !!global_options[:verbose]
|
50
|
+
@@settings.silent = !!global_options[:silent]
|
51
|
+
@@settings.definitions_dir = File.expand_path(
|
52
|
+
global_options["definitions-dir"]
|
53
|
+
) if global_options["definitions-dir"]
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
on_error do |e|
|
58
|
+
case e
|
59
|
+
when GLI::UnknownCommandArgument, GLI::UnknownGlobalArgument,
|
60
|
+
GLI::UnknownCommand, GLI::BadCommandLine
|
61
|
+
STDERR.puts e.to_s + "\n\n"
|
62
|
+
command = ARGV & @commands.keys.map(&:to_s)
|
63
|
+
run(command << "--help")
|
64
|
+
exit 1
|
65
|
+
when SystemExit
|
66
|
+
raise
|
67
|
+
when SignalException
|
68
|
+
exit 1
|
69
|
+
else
|
70
|
+
STDERR.puts "Pennyworth experienced an unexpected error. Please file a " \
|
71
|
+
"bug report at https://github.com/SUSE/pennyworth/issues/new.\n"
|
72
|
+
if e.is_a?(Cheetah::ExecutionFailed)
|
73
|
+
result = ""
|
74
|
+
result << "#{e.message}\n"
|
75
|
+
result << "\n"
|
76
|
+
|
77
|
+
if e.stderr && !e.stderr.empty?
|
78
|
+
result << "Error output:\n"
|
79
|
+
result << "#{e.stderr}\n"
|
80
|
+
end
|
81
|
+
|
82
|
+
if e.stdout && !e.stdout.empty?
|
83
|
+
result << "Standard output:\n"
|
84
|
+
result << "#{e.stdout}\n\n"
|
85
|
+
end
|
86
|
+
|
87
|
+
if e.backtrace && !e.backtrace.empty?
|
88
|
+
result << "Backtrace:\n"
|
89
|
+
result << "#{e.backtrace.join("\n")}\n\n"
|
90
|
+
end
|
91
|
+
STDERR.puts result
|
92
|
+
exit 1
|
93
|
+
else
|
94
|
+
raise
|
95
|
+
end
|
96
|
+
end
|
97
|
+
true
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.settings
|
101
|
+
@@settings
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.settings= s
|
105
|
+
@@settings = s
|
106
|
+
end
|
107
|
+
|
108
|
+
desc "Prepare system for running Pennyworth"
|
109
|
+
long_desc <<-LONGDESC
|
110
|
+
Prepare the system to be able to run virtual machines via Pennyworth. This
|
111
|
+
encapsulates package installation as well as set up of required tools such
|
112
|
+
as Vagrant and libvirt.
|
113
|
+
|
114
|
+
See https://github.com/SUSE/pennyworth#installation for more information.
|
115
|
+
LONGDESC
|
116
|
+
command :setup do |c|
|
117
|
+
c.action do |global_options,options,args|
|
118
|
+
SetupCommand.new.execute
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
desc "Show status of virtual machine"
|
123
|
+
long_desc <<-LONGDESC
|
124
|
+
Show status of specified virtual machine. Use `list` to get a list of all
|
125
|
+
available machines.
|
126
|
+
LONGDESC
|
127
|
+
arg_name "VM_NAME"
|
128
|
+
command :status do |c|
|
129
|
+
c.action do |global_options,options,args|
|
130
|
+
vm_name = args.shift
|
131
|
+
VagrantCommand.setup_environment(@@settings.vagrant_dir)
|
132
|
+
StatusCommand.new.execute(vm_name)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
desc "Build base images"
|
137
|
+
long_desc <<-LONGDESC
|
138
|
+
Build base images used by Vagrant. If no specific name is given all base
|
139
|
+
images are built. The images have to be imported with `import-base` to be
|
140
|
+
available to be run.
|
141
|
+
LONGDESC
|
142
|
+
arg_name "IMAGE_NAME", :optional
|
143
|
+
command "build-base" do |c|
|
144
|
+
c.flag [:kiwi_tmp_dir, :k], :type => String, :required => false,
|
145
|
+
:desc => "Temporary KIWI directory for building the Vagrant box.",
|
146
|
+
:arg_name => "KIWI-TMP-Dir"
|
147
|
+
c.action do |global_options,options,args|
|
148
|
+
image_name = args.shift
|
149
|
+
tmp_dir = options[:kiwi_tmp_dir] || "/tmp/pennyworth-kiwi-builds"
|
150
|
+
BuildBaseCommand.new(Cli.settings.kiwi_dir).execute(tmp_dir, image_name)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
desc "Import base images"
|
155
|
+
long_desc <<-LONGDESC
|
156
|
+
Import base images used by Vagrant. If no specific name is given all base
|
157
|
+
images are imported. Base images have to be built with `build-base` or
|
158
|
+
imported from a remote location specified with the `--url` option.
|
159
|
+
LONGDESC
|
160
|
+
arg_name "IMAGE_NAME", :optional
|
161
|
+
command "import-base" do |c|
|
162
|
+
c.flag [:url, :u], :type => String, :required => false,
|
163
|
+
:desc => "URL of the remote server where the images will be imported from", :arg_name => "URL"
|
164
|
+
c.action do |global_options,options,args|
|
165
|
+
image_name = args.shift
|
166
|
+
VagrantCommand.setup_environment(@@settings.vagrant_dir)
|
167
|
+
if options[:url]
|
168
|
+
kiwi_dir = File.expand_path("~/.pennyworth/kiwi")
|
169
|
+
remote_url = options[:url]
|
170
|
+
opts = {
|
171
|
+
local: false,
|
172
|
+
}
|
173
|
+
else
|
174
|
+
if !Cli.settings.definitions_dir
|
175
|
+
STDERR.puts "You need to specify a definitions directory when not using --url."
|
176
|
+
exit 1
|
177
|
+
end
|
178
|
+
kiwi_dir = Cli.settings.kiwi_dir
|
179
|
+
opts = {
|
180
|
+
local: true
|
181
|
+
}
|
182
|
+
end
|
183
|
+
ImportBaseCommand.new(kiwi_dir, remote_url).execute(image_name, opts)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
desc "Start virtual machine"
|
188
|
+
long_desc <<-LONGDESC
|
189
|
+
Start specified virtual machine
|
190
|
+
LONGDESC
|
191
|
+
arg_name "VM_NAME"
|
192
|
+
command :up do |c|
|
193
|
+
c.switch [:destroy], :default_value => false, :required => false, :negatable => false,
|
194
|
+
:desc => "Destroy vagrant instance(s) before starting them."
|
195
|
+
c.action do |global_options,options,args|
|
196
|
+
vm_name = args.shift
|
197
|
+
VagrantCommand.setup_environment(@@settings.vagrant_dir)
|
198
|
+
UpCommand.new.execute(vm_name, options)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
desc "Stop virtual machine"
|
203
|
+
long_desc <<-LONGDESC
|
204
|
+
Stop specified virtual machine
|
205
|
+
LONGDESC
|
206
|
+
arg_name "VM_NAME"
|
207
|
+
command :down do |c|
|
208
|
+
c.action do |global_options,options,args|
|
209
|
+
vm_name = args.shift
|
210
|
+
VagrantCommand.setup_environment(@@settings.vagrant_dir)
|
211
|
+
DownCommand.new.execute(vm_name)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
desc "Copy puplic SSH keys to target system"
|
216
|
+
long_desc <<-LONGDESC
|
217
|
+
Copy the public SSH keys to the host named IP-ADDRESS for easy root access
|
218
|
+
LONGDESC
|
219
|
+
arg_name "IP-ADDRESS"
|
220
|
+
command :copy_ssh_keys do |c|
|
221
|
+
c.flag [:password, :p], :type => String, :required => false,
|
222
|
+
:desc => "Password", :arg_name => "PASSWORD"
|
223
|
+
c.action do |global_options,options,args|
|
224
|
+
if !args.empty?
|
225
|
+
ip = args.shift
|
226
|
+
else
|
227
|
+
raise GLI::BadCommandLine.new("You need to provide the IP of the target system as argument.")
|
228
|
+
end
|
229
|
+
|
230
|
+
ImportSshKeysCommand.new.execute(ip, options)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
desc "List available machines and images"
|
235
|
+
long_desc <<-LONGDESC
|
236
|
+
List virtual machines, base images, and related data
|
237
|
+
LONGDESC
|
238
|
+
command :list do |c|
|
239
|
+
c.action do |global_options,options,args|
|
240
|
+
VagrantCommand.setup_environment(@@settings.vagrant_dir)
|
241
|
+
ListCommand.new(Cli.settings.kiwi_dir).execute
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
desc "Boot custom image file"
|
246
|
+
long_desc <<-LONGDESC
|
247
|
+
Boot a custom image from the given file IMAGE in a VM not managed by
|
248
|
+
Vagrant. You can shut down an image booted this way with `shutdown`.
|
249
|
+
LONGDESC
|
250
|
+
arg_name "IMAGE"
|
251
|
+
command :boot do |c|
|
252
|
+
c.action do |global_options,options,args|
|
253
|
+
if !args.empty?
|
254
|
+
image = File.expand_path(args.shift)
|
255
|
+
else
|
256
|
+
raise GLI::BadCommandLine.new("You need to provide the name of the image to boot as argument.")
|
257
|
+
end
|
258
|
+
VagrantCommand.setup_environment(@@settings.vagrant_dir)
|
259
|
+
BootCommand.new.execute(image)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
desc "Shutdown custom image"
|
264
|
+
long_desc <<-LONGDESC
|
265
|
+
Shutdown custom image, which was started with `boot`.
|
266
|
+
LONGDESC
|
267
|
+
arg_name "IMAGE"
|
268
|
+
command :shutdown do |c|
|
269
|
+
c.action do |global_options,options,args|
|
270
|
+
if !args.empty?
|
271
|
+
image = args.shift
|
272
|
+
else
|
273
|
+
raise GLI::BadCommandLine.new("You need to provide the name of the VM to shutdown as argument.")
|
274
|
+
end
|
275
|
+
VagrantCommand.setup_environment(@@settings.vagrant_dir)
|
276
|
+
ShutdownCommand.new.execute(name)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def self.host_controller
|
281
|
+
CliHostController.new("~/.pennyworth", STDOUT)
|
282
|
+
end
|
283
|
+
|
284
|
+
desc "Manage test hosts"
|
285
|
+
long_desc <<-LONGDESC
|
286
|
+
This subcommand provides the tools to manage existing machines to be used
|
287
|
+
as test hosts. Hosts are defined in the configuration file
|
288
|
+
`.pennyworth/hosts.yaml`.
|
289
|
+
|
290
|
+
See https://github.com/SUSE/pennyworth#using-existing-hosts for more
|
291
|
+
information.
|
292
|
+
LONGDESC
|
293
|
+
command :host do |c|
|
294
|
+
c.desc "Fetch host configuration"
|
295
|
+
c.long_desc <<-LONGDESC
|
296
|
+
Fetch initial host configuration from a given URL. This can be used to
|
297
|
+
share configuration across multiple machines and users. The argument has
|
298
|
+
to be the URL to the remote configuration file.
|
299
|
+
LONGDESC
|
300
|
+
c.arg_name "URL"
|
301
|
+
c.command :setup do |sc|
|
302
|
+
sc.action do |_, _, args|
|
303
|
+
Cli.host_controller.setup(args[0])
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
c.desc "List available hosts"
|
308
|
+
c.command :list do |sc|
|
309
|
+
sc.action do
|
310
|
+
Cli.host_controller.list
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
c.desc "Lock host"
|
315
|
+
c.arg_name "HOST-NAME"
|
316
|
+
c.command :lock do |sc|
|
317
|
+
sc.action do |_, _, args|
|
318
|
+
Cli.host_controller.lock(args[0])
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
c.desc "Reset host to defined state"
|
323
|
+
c.arg_name "HOST-NAME"
|
324
|
+
c.command :reset do |sc|
|
325
|
+
sc.action do |_, _, args|
|
326
|
+
Cli.host_controller.reset(args[0])
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
c.desc "Show information about host"
|
331
|
+
c.arg_name "HOST-NAME"
|
332
|
+
c.command :info do |sc|
|
333
|
+
sc.action do |_, _, args|
|
334
|
+
Cli.host_controller.info(args[0])
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|