vmit 0.0.3

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.
@@ -0,0 +1,273 @@
1
+ #
2
+ # Copyright (C) 2013 Duncan Mac-Vicar P. <dmacvicar@suse.de>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ #
21
+ require 'vmit'
22
+ require 'vmit/autoyast'
23
+ require 'vmit/kickstart'
24
+ require 'vmit/debian_preseed'
25
+
26
+ module Vmit
27
+
28
+ module Bootstrap
29
+
30
+ def self.arch
31
+ Cheetah.run('arch', :stdout => :capture).strip
32
+ end
33
+
34
+ def self.bootstrapper_for(location)
35
+ case
36
+ when local_iso
37
+ end
38
+ end
39
+
40
+ module MethodDebianPreseed
41
+ # @param [Hash] args Arguments for 1st stage
42
+ def execute_autoinstall(args)
43
+ auto_install_args = {}
44
+ preseed = Vmit::DebianPreseed.new
45
+
46
+ Dir.mktmpdir do |floppy_dir|
47
+ qemu_args = {:floppy => floppy_dir,
48
+ :append => "preseed/file=/floppy/preseed.cfg auto=true priority=critical",
49
+ :reboot => false}
50
+ qemu_args.merge!(auto_install_args)
51
+ # transform duplicates into an array
52
+ qemu_args.merge!(args) do |key, oldv, newv|
53
+ case key
54
+ when :append then [oldv, newv].flatten
55
+ else newv
56
+ end
57
+ end
58
+
59
+ # Configure the autoinstallation profile to persist eth0
60
+ # for the current MAC address
61
+ # The interface will be setup with DHCP by default.
62
+ # TODO: make this more flexible in the future?
63
+ #autoyast.name_network_device(vm[:mac_address], 'eth0')
64
+ File.write(File.join(floppy_dir, 'preseed.cfg'), preseed.to_txt)
65
+ Vmit.logger.info "Preseed: 1st stage."
66
+ vm.run(qemu_args)
67
+ Vmit.logger.info "Preseed: 2st stage."
68
+ # 2nd stage
69
+ vm.run(:reboot => false)
70
+ end
71
+ end
72
+ end
73
+
74
+ module MethodKickstart
75
+ # @param [Hash] args Arguments for 1st stage
76
+ def execute_autoinstall(args)
77
+ auto_install_args = {}
78
+ kickstart = Vmit::Kickstart.new
79
+
80
+ case media
81
+ when Vmit::VFS::URI
82
+ kickstart.install = location
83
+ when Vmit::VFS::ISO
84
+ kickstart.install = :cdrom
85
+ auto_install_args.merge!(:cdrom => location.to_s)
86
+ else raise ArgumentError.new("Unsupported autoinstallation: #{location}")
87
+ end
88
+
89
+ Dir.mktmpdir do |floppy_dir|
90
+ qemu_args = {:floppy => floppy_dir,
91
+ :append => "ks=floppy repo=#{kickstart.install}",
92
+ :reboot => false}
93
+ qemu_args.merge!(auto_install_args)
94
+ # transform duplicates into an array
95
+ qemu_args.merge!(args) do |key, oldv, newv|
96
+ case key
97
+ when :append then [oldv, newv].flatten
98
+ else newv
99
+ end
100
+ end
101
+
102
+ File.write(File.join(floppy_dir, 'ks.cfg'), kickstart.to_ks_script)
103
+ Vmit.logger.info "Kickstart: 1st stage."
104
+ vm.run(qemu_args)
105
+ end
106
+ end
107
+ end
108
+
109
+ module MethodAutoYaST
110
+ # @param [Hash] args Arguments for 1st stage
111
+ def execute_autoinstall(args)
112
+ auto_install_args = {}
113
+ auto_install_args.merge!(args)
114
+ kernel_append_arg = case media
115
+ when Vmit::VFS::URI then "install=#{location}"
116
+ when Vmit::VFS::ISO then 'install=cdrom'
117
+ else raise ArgumentError.new("Unsupported autoinstallation: #{location}")
118
+ end
119
+ auto_install_args.merge!(:append => kernel_append_arg)
120
+ if media.is_a?(Vmit::VFS::ISO)
121
+ auto_install_args.merge!(:cdrom => location.to_s)
122
+ end
123
+
124
+ Dir.mktmpdir do |floppy_dir|
125
+ qemu_args = {:floppy => floppy_dir,
126
+ :append => "autoyast=device://fd0/autoinst.xml",
127
+ :reboot => false}
128
+ # transform duplicates into an array
129
+ qemu_args.merge!(auto_install_args) do |key, oldv, newv|
130
+ case key
131
+ when :append then [oldv, newv].flatten
132
+ else newv
133
+ end
134
+ end
135
+
136
+ autoyast = Vmit::AutoYaST.new
137
+
138
+ # WTF SLE and openSUSE have different
139
+ # base pattern names
140
+ media.open('/content') do |content_file|
141
+ content_file.each_line do |line|
142
+ case line
143
+ when /^DISTRIBUTION (.+)$/
144
+ case $1
145
+ when /SUSE_SLE/ then autoyast.minimal_sle!
146
+ when /openSUSE/ then autoyast.minimal_opensuse!
147
+ end
148
+ end
149
+ end
150
+ end
151
+
152
+ # Configure the autoinstallation profile to persist eth0
153
+ # for the current MAC address
154
+ # The interface will be setup with DHCP by default.
155
+ # TODO: make this more flexible in the future?
156
+ #autoyast.name_network_device(vm[:mac_address], 'eth0')
157
+ File.write(File.join(floppy_dir, 'autoinst.xml'), autoyast.to_xml)
158
+ Vmit.logger.info "AutoYaST: 1st stage."
159
+ vm.run(qemu_args)
160
+ Vmit.logger.info "AutoYaST: 2st stage."
161
+ # 2nd stage
162
+ vm.run(:reboot => false)
163
+ end
164
+ end
165
+ end
166
+
167
+ module SUSEMedia
168
+ include MethodAutoYaST
169
+
170
+ def get_initrd
171
+ media.open("/boot/#{Vmit::Bootstrap.arch}/loader/initrd")
172
+ end
173
+
174
+ def get_kernel
175
+ media.open("/boot/#{Vmit::Bootstrap.arch}/loader/linux")
176
+ end
177
+ end
178
+
179
+ module FedoraMedia
180
+ include MethodKickstart
181
+
182
+ def get_initrd
183
+ media.open("/images/pxeboot/initrd.img")
184
+ end
185
+
186
+ def get_kernel
187
+ media.open("/images/pxeboot/vmlinuz")
188
+ end
189
+ end
190
+
191
+ module DebianMedia
192
+ include MethodDebianPreseed
193
+
194
+ def get_initrd
195
+ arch = Vmit::Bootstrap.arch.gsub(/x86_64/, 'amd64')
196
+ media.open("/main/installer-#{arch}/current/images/netboot/debian-installer/#{arch}/initrd.gz")
197
+ end
198
+
199
+ def get_kernel
200
+ arch = Vmit::Bootstrap.arch.gsub(/x86_64/, 'amd64')
201
+ media.open("/main/installer-#{arch}/current/images/netboot/debian-installer/#{arch}/linux")
202
+ end
203
+ end
204
+
205
+ # Boostraps a vm from a SUSE repository
206
+ class FromMedia
207
+
208
+ attr_reader :vm
209
+ attr_reader :media
210
+ attr_reader :location
211
+
212
+ # @param [URI] location
213
+ def self.accept?(location)
214
+ # either a local ISO or a remote repository
215
+ # (and not a remote file, but we don't have
216
+ # a good way to check)
217
+ Vmit::VFS::ISO.accept?(location) ||
218
+ (Vmit::VFS::URI.accept?(location) &&
219
+ File.extname(location.to_s) == '')
220
+ end
221
+
222
+ def initialize(vm, location)
223
+ @location = location
224
+ @vm = vm
225
+ @media = Vmit::VFS.from(location)
226
+
227
+ # TODO FIXME we need a clever way to detect the
228
+ # location distro type. I could uname the kernel, but
229
+ # I need the type to know the location.
230
+ media_handler = case location.to_s.downcase
231
+ when /fedora|redhat|centos/ then FedoraMedia
232
+ when /suse/ then SUSEMedia
233
+ when /debian/ then DebianMedia
234
+ else
235
+ raise "Don't know how to bootstrap media #{location}"
236
+ end
237
+ self.extend media_handler
238
+
239
+ @boot_kernel = get_kernel
240
+ @boot_initrd = get_initrd
241
+ end
242
+
243
+ def execute
244
+ args = {}
245
+ args.merge!({:kernel => @boot_kernel.path, :initrd => @boot_initrd.path})
246
+ execute_autoinstall(args)
247
+ end
248
+ end
249
+
250
+ class FromImage
251
+
252
+ # @param [URI] location
253
+ def self.accept?(location)
254
+ uri = case location
255
+ when ::URI then location
256
+ else ::URI.parse(location.to_s)
257
+ end
258
+ return false unless ['.raw', '.qcow2'].include?(File.extname(uri.to_s))
259
+ uri.scheme == 'http' || File.exist?(uri.to_s)
260
+ end
261
+
262
+ def initialize(vm, location)
263
+ @location = location
264
+ #http://download.suse.de/ibs/Devel:/Galaxy:/Manager:/1.7:/Appliance/images/SUSE_Manager_Server_pg_Devel.x86_64-1.7.0-Build3.126.raw.xz
265
+ end
266
+
267
+ def execute
268
+ Vmit.logger.info "From media!!!"
269
+ end
270
+ end
271
+
272
+ end
273
+ end
@@ -0,0 +1,64 @@
1
+ #
2
+ # Copyright (C) 2013 Duncan Mac-Vicar P. <dmacvicar@suse.de>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ #
21
+ require 'erb'
22
+
23
+ module Vmit
24
+
25
+ # Some good references here:
26
+ # http://www.hps.com/~tpg/notebook/autoinstall.php
27
+ class DebianPreseed
28
+
29
+ def to_txt
30
+ template = ERB.new <<-EOF
31
+ d-i debian-installer/locale string en_US
32
+ d-i console-tools/archs select at
33
+ d-i console-keymaps-at/keymap select American English
34
+ d-i debian-installer/keymap string us
35
+ d-i netcfg/get_hostname string unassigned-hostname
36
+ d-i netcfg/get_hostname seen true
37
+ d-i netcfg/get_domain string unassigned-domain
38
+ d-i netcfg/get_domain seen true
39
+ d-i mirror/protocol string ftp
40
+ d-i mirror/ftp/hostname string ftp.de.debian.org
41
+ d-i mirror/ftp/directory string /debian/
42
+ d-i mirror/ftp/proxy string
43
+
44
+ d-i partman-auto/method string regular
45
+ d-i partman-partitioning/confirm_write_new_label boolean true
46
+ d-i partman/choose_partition select finish
47
+ d-i partman/confirm boolean true
48
+ d-i partman/confirm_nooverwrite boolean true
49
+
50
+ d-i clock-setup/utc boolean true
51
+ d-i time/zone string US/Eastern
52
+ d-i clock-setup/ntp boolean true
53
+ popularity-contest popularity-contest/participate boolean false
54
+ d-i pkgsel/include string ssh rsync initrd-tools cramfsprogs lzop
55
+ d-i passwd/root-password password linux
56
+ d-i passwd/root-password-again password linux
57
+ d-i passwd/make-user boolean false
58
+ d-i grub-installer/only_debian boolean true
59
+ EOF
60
+ return template.result(binding)
61
+ end
62
+
63
+ end
64
+ end
data/lib/vmit/ext.rb ADDED
@@ -0,0 +1,38 @@
1
+ #
2
+ # Copyright (C) 2013 Duncan Mac-Vicar P. <dmacvicar@suse.de>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ #
21
+
22
+ module Vmit
23
+ module Ext
24
+
25
+ module Hash
26
+ def symbolize_keys
27
+ Hash[map{|(k,v)| [k.to_sym,v]}]
28
+ end
29
+
30
+ def symbolize_keys!
31
+ replace(symbolize_keys)
32
+ end
33
+ end
34
+
35
+ end
36
+ end
37
+
38
+ Hash.send(:include, Vmit::Ext::Hash)
@@ -0,0 +1,67 @@
1
+ #
2
+ # Copyright (C) 2013 Duncan Mac-Vicar P. <dmacvicar@suse.de>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ #
21
+ require 'vmit'
22
+ require 'erb'
23
+
24
+ module Vmit
25
+
26
+ class Kickstart
27
+
28
+ attr_accessor :install
29
+
30
+ # ks=floppy
31
+ def initialize
32
+ end
33
+
34
+ def to_ks_script
35
+ template = ERB.new <<-EOF
36
+ cmdline
37
+ halt
38
+ rootpw linux
39
+ lang en_US.UTF-8
40
+ keyboard us
41
+ timezone --utc America/New_York
42
+ bootloader --location=mbr --driveorder=sda --append="rhgb quiet"
43
+ install
44
+ <% if install.is_a?(String) || install.is_a?(::URI)%>
45
+ url --url=<%= install.to_s.strip %>
46
+ <% else %>
47
+ <%= install %>
48
+ <% end %>
49
+ network --device eth0 --bootproto dhcp
50
+ zerombr yes
51
+ clearpart --all --initlabel
52
+ autopart
53
+ %packages --nobase
54
+ @core
55
+ @server-policy
56
+ wget
57
+ mc
58
+
59
+ %end
60
+ EOF
61
+ template.result(binding)
62
+ end
63
+
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,66 @@
1
+ #
2
+ # Copyright (C) 2013 Duncan Mac-Vicar P. <dmacvicar@suse.de>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ #
21
+ require 'logger'
22
+ require 'cheetah'
23
+
24
+ module Vmit
25
+
26
+ # remote log service for
27
+ # qemu ifup ifdown scripts
28
+ class LogServer
29
+ def method_missing(name, *args)
30
+ Vmit.logger.send(name, *args)
31
+ end
32
+ end
33
+
34
+ # Cheetah says it supports a logger
35
+ # for debugging but then adds entries
36
+ # with INFO instead of DEBUG
37
+ class CheetahLoggerAdapter
38
+ def initialize(logger)
39
+ @logger = logger
40
+ end
41
+
42
+ def info(message)
43
+ @logger.debug(message)
44
+ end
45
+
46
+ def error(message)
47
+ @logger.error(message)
48
+ end
49
+ end
50
+
51
+ def self.logger=(logger)
52
+ @logger = logger
53
+ end
54
+
55
+ def self.logger
56
+ if @logger.nil?
57
+ logger = Logger.new(STDERR)
58
+ logger.level = Logger::INFO
59
+ logger.level = Logger::DEBUG if ENV['DEBUG']
60
+ Vmit.logger = logger
61
+ Cheetah.default_options = {:logger => CheetahLoggerAdapter.new(logger)}
62
+ end
63
+ @logger
64
+ end
65
+
66
+ end