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
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
|