pennyworth-tool 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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