pennyworth-tool 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.hound.yml +3 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +18 -0
  6. data/CONTRIBUTING.md +67 -0
  7. data/COPYING +674 -0
  8. data/Gemfile +28 -0
  9. data/README.md +339 -0
  10. data/Rakefile +33 -0
  11. data/bin/pennyworth +26 -0
  12. data/config/setup.yml +17 -0
  13. data/examples/README.md +23 -0
  14. data/examples/kiwi/definitions/base_opensuse13.1_kvm/config.sh +87 -0
  15. data/examples/kiwi/definitions/base_opensuse13.1_kvm/config.xml +64 -0
  16. data/examples/kiwi/definitions/base_opensuse13.1_kvm/root/etc/sysconfig/network/ifcfg-eth0 +2 -0
  17. data/examples/kiwi/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  18. data/examples/vagrant/Vagrantfile +14 -0
  19. data/files/99-libvirt.rules +2 -0
  20. data/files/image_test-template.xml +43 -0
  21. data/files/pool-default.xml +6 -0
  22. data/lib/image_runner.rb +89 -0
  23. data/lib/pennyworth.rb +65 -0
  24. data/lib/pennyworth/cli.rb +339 -0
  25. data/lib/pennyworth/cli_host_controller.rb +107 -0
  26. data/lib/pennyworth/commands/base_command.rb +96 -0
  27. data/lib/pennyworth/commands/boot_command.rb +29 -0
  28. data/lib/pennyworth/commands/build_base_command.rb +103 -0
  29. data/lib/pennyworth/commands/command.rb +43 -0
  30. data/lib/pennyworth/commands/down_command.rb +25 -0
  31. data/lib/pennyworth/commands/import_base_command.rb +112 -0
  32. data/lib/pennyworth/commands/import_ssh_keys_command.rb +27 -0
  33. data/lib/pennyworth/commands/list_command.rb +41 -0
  34. data/lib/pennyworth/commands/setup_command.rb +209 -0
  35. data/lib/pennyworth/commands/shutdown_command.rb +28 -0
  36. data/lib/pennyworth/commands/status_command.rb +26 -0
  37. data/lib/pennyworth/commands/up_command.rb +27 -0
  38. data/lib/pennyworth/exceptions.rb +39 -0
  39. data/lib/pennyworth/helper.rb +39 -0
  40. data/lib/pennyworth/host_config.rb +86 -0
  41. data/lib/pennyworth/host_runner.rb +133 -0
  42. data/lib/pennyworth/image_runner.rb +89 -0
  43. data/lib/pennyworth/libvirt.rb +93 -0
  44. data/lib/pennyworth/local_command_runner.rb +77 -0
  45. data/lib/pennyworth/local_runner.rb +34 -0
  46. data/lib/pennyworth/lock_service.rb +87 -0
  47. data/lib/pennyworth/remote_command_runner.rb +144 -0
  48. data/lib/pennyworth/runner.rb +27 -0
  49. data/lib/pennyworth/settings.rb +42 -0
  50. data/lib/pennyworth/spec.rb +96 -0
  51. data/lib/pennyworth/spec_profiler.rb +85 -0
  52. data/lib/pennyworth/ssh_keys_importer.rb +107 -0
  53. data/lib/pennyworth/urls.rb +28 -0
  54. data/lib/pennyworth/vagrant.rb +81 -0
  55. data/lib/pennyworth/vagrant_command.rb +120 -0
  56. data/lib/pennyworth/vagrant_runner.rb +44 -0
  57. data/lib/pennyworth/version.rb +22 -0
  58. data/lib/pennyworth/vm.rb +62 -0
  59. data/man/.gitignore +2 -0
  60. data/man/pennyworth.1.md +28 -0
  61. data/pennyworth.gemspec +57 -0
  62. data/prophet/Gemfile +3 -0
  63. data/prophet/prophet.rb +82 -0
  64. data/spec/base_command_spec.rb +30 -0
  65. data/spec/build_base_command_spec.rb +147 -0
  66. data/spec/cli_host_controller_spec.rb +113 -0
  67. data/spec/data/hosts.yaml +10 -0
  68. data/spec/data/kiwi/base_opensuse12.3_kvm.box +1 -0
  69. data/spec/data/kiwi/base_opensuse13.1_kvm.box +1 -0
  70. data/spec/data/kiwi/definitions/base_opensuse12.3_kvm/config.sh +1 -0
  71. data/spec/data/kiwi/definitions/base_opensuse12.3_kvm/config.xml +1 -0
  72. data/spec/data/kiwi/definitions/base_opensuse12.3_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  73. data/spec/data/kiwi/definitions/base_opensuse13.1_kvm/config.sh +1 -0
  74. data/spec/data/kiwi/definitions/base_opensuse13.1_kvm/config.xml +1 -0
  75. data/spec/data/kiwi/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  76. data/spec/data/kiwi2/box_state.yaml +14 -0
  77. data/spec/data/kiwi2/definitions/base_opensuse12.3_kvm/config.sh +1 -0
  78. data/spec/data/kiwi2/definitions/base_opensuse12.3_kvm/config.xml +1 -0
  79. data/spec/data/kiwi2/definitions/base_opensuse12.3_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  80. data/spec/data/kiwi2/definitions/base_opensuse13.1_kvm/config.sh +1 -0
  81. data/spec/data/kiwi2/definitions/base_opensuse13.1_kvm/config.xml +1 -0
  82. data/spec/data/kiwi2/definitions/base_opensuse13.1_kvm/root/home/vagrant/.ssh/authorized_keys +1 -0
  83. data/spec/data/kiwi3/box_state.yaml +13 -0
  84. data/spec/data/kiwi3/definitions/base_opensuse12.3_kvm/.gitkeep +0 -0
  85. data/spec/data/kiwi3/definitions/base_opensuse13.1_kvm/.gitkeep +0 -0
  86. data/spec/data/kiwi3/import_state.yaml +3 -0
  87. data/spec/data/kiwi4/definitions/base_opensuse12.3_kvm/.gitkeep +0 -0
  88. data/spec/data/kiwi4/definitions/base_opensuse13.1_kvm/.gitkeep +0 -0
  89. data/spec/data/kiwi4/import_state.yaml +3 -0
  90. data/spec/data/kiwi5/import_state.yaml +3 -0
  91. data/spec/data/vagrant/.gitkeep +0 -0
  92. data/spec/host_config_spec.rb +197 -0
  93. data/spec/host_runner_spec.rb +112 -0
  94. data/spec/image_runner_spec.rb +62 -0
  95. data/spec/import_base_command_spec.rb +189 -0
  96. data/spec/local_command_runner_spec.rb +117 -0
  97. data/spec/local_runner_spec.rb +42 -0
  98. data/spec/lock_service_spec.rb +95 -0
  99. data/spec/remote_command_runner_spec.rb +115 -0
  100. data/spec/settings_spec.rb +26 -0
  101. data/spec/setup_command_spec.rb +49 -0
  102. data/spec/spec_helper.rb +50 -0
  103. data/spec/spec_profiler_spec.rb +63 -0
  104. data/spec/spec_spec.rb +99 -0
  105. data/spec/support/command_runner_examples.rb +29 -0
  106. data/spec/support/runner_examples.rb +34 -0
  107. data/spec/urls_spec.rb +46 -0
  108. data/spec/vagrant_command_spec.rb +51 -0
  109. data/spec/vagrant_runner_spec.rb +40 -0
  110. data/spec/vagrant_spec.rb +288 -0
  111. data/spec/vm_spec.rb +56 -0
  112. metadata +257 -0
@@ -0,0 +1,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,2 @@
1
+ STARTMODE=onboot
2
+ BOOTPROTO=dhcp
@@ -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,2 @@
1
+ 'org.libvirt.unix.monitor':
2
+ [ 'yes', 'yes', 'yes' ]
@@ -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>
@@ -0,0 +1,6 @@
1
+ <pool type="dir">
2
+ <name>default</name>
3
+ <target>
4
+ <path>/var/lib/libvirt/images</path>
5
+ </target>
6
+ </pool>
@@ -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