| Class | BoxGrinder::GuestFSHelper |
| In: |
lib/boxgrinder-build/helpers/guestfs-helper.rb
lib/boxgrinder-build/helpers/guestfs-helper.rb |
| Parent: | Object |
| guestfs | [R] | |
| guestfs | [R] |
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 29
29: def initialize(disks, appliance_config, config, options = {})
30: @disks = disks
31: @appliance_config = appliance_config
32: @config = config
33: @log = options[:log] || LogHelper.new
34: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 29
29: def initialize(disks, appliance_config, config, options = {})
30: @disks = disks
31: @appliance_config = appliance_config
32: @config = config
33: @log = options[:log] || LogHelper.new
34: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 299
299: def augeas(&block)
300: AugeasHelper.new(@guestfs, self, :log => @log).edit(&block)
301: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 299
299: def augeas(&block)
300: AugeasHelper.new(@guestfs, self, :log => @log).edit(&block)
301: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 231
231: def clean_close
232: @log.trace "Closing guestfs..."
233:
234: @guestfs.sync
235: @guestfs.umount_all
236: @guestfs.close
237:
238: @log.trace "Guestfs closed."
239: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 231
231: def clean_close
232: @log.trace "Closing guestfs..."
233:
234: @guestfs.sync
235: @guestfs.umount_all
236: @guestfs.close
237:
238: @log.trace "Guestfs closed."
239: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 172
172: def customize(options = {})
173: initialize_guestfs(options) do
174: helper = execute(options)
175:
176: yield @guestfs, helper
177:
178: clean_close
179: end
180: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 172
172: def customize(options = {})
173: initialize_guestfs(options) do
174: helper = execute(options)
175:
176: yield @guestfs, helper
177:
178: clean_close
179: end
180: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 182
182: def execute(options = {})
183: options = {
184: :ide_disk => false,
185: :mount_prefix => '',
186: :automount => true,
187: :load_selinux_policy => true
188: }.merge(options)
189:
190: @log.debug "Launching guestfs..."
191: @guestfs.launch
192:
193: if options[:automount]
194: device = @guestfs.list_devices.first
195:
196: if @guestfs.list_partitions.size == 0
197: mount_partition(device, '/', options[:mount_prefix])
198: else
199: mount_partitions(device, options[:mount_prefix])
200: end
201:
202: load_selinux_policy if options[:load_selinux_policy]
203: end
204:
205: @log.trace "Guestfs launched."
206:
207: self
208: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 182
182: def execute(options = {})
183: options = {
184: :ide_disk => false,
185: :mount_prefix => '',
186: :automount => true,
187: :load_selinux_policy => true
188: }.merge(options)
189:
190: @log.debug "Launching guestfs..."
191: @guestfs.launch
192:
193: if options[:automount]
194: device = @guestfs.list_devices.first
195:
196: if @guestfs.list_partitions.size == 0
197: mount_partition(device, '/', options[:mount_prefix])
198: else
199: mount_partitions(device, options[:mount_prefix])
200: end
201:
202: load_selinux_policy if options[:load_selinux_policy]
203: end
204:
205: @log.trace "Guestfs launched."
206:
207: self
208: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 38
38: def hw_virtualization_available?
39: @log.trace "Checking if HW virtualization is available..."
40:
41: ec2 = false
42:
43: begin
44: Timeout::timeout(2) { ec2 = Net::HTTP.get_response(URI.parse('http://169.254.169.254/latest/meta-data/ami-id')).code.eql?("200") }
45: rescue Exception
46: end
47:
48: if `egrep '^flags.*(vmx|svm)' /proc/cpuinfo | wc -l`.chomp.strip.to_i > 0 and !ec2
49: @log.trace "HW acceleration available."
50: return true
51: end
52:
53: @log.trace "HW acceleration not available."
54:
55: false
56: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 38
38: def hw_virtualization_available?
39: @log.trace "Checking if HW virtualization is available..."
40:
41: ec2 = false
42:
43: begin
44: Timeout::timeout(2) { ec2 = Net::HTTP.get_response(URI.parse('http://169.254.169.254/latest/meta-data/ami-id')).code.eql?("200") }
45: rescue Exception
46: end
47:
48: if `egrep '^flags.*(vmx|svm)' /proc/cpuinfo | wc -l`.chomp.strip.to_i > 0 and !ec2
49: @log.trace "HW acceleration available."
50: return true
51: end
52:
53: @log.trace "HW acceleration not available."
54:
55: false
56: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 112
112: def initialize_guestfs(options = {})
113: @log.debug "Preparing guestfs..."
114: @log.trace "Setting libguestfs temporary directory to '#{@config.dir.tmp}'..."
115:
116: FileUtils.mkdir_p(@config.dir.tmp)
117: ENV['TMPDIR'] = @config.dir.tmp
118:
119: @guestfs = Guestfs::create
120:
121: if @guestfs.respond_to?(:set_event_callback)
122: @log.trace "We have event callbacks available!"
123: log_callback { prepare_guestfs(options) { yield } }
124: else
125: @log.trace "We don't have event callbacks available :( Falling back to proxy."
126: log_hack { prepare_guestfs(options) { yield } }
127: end
128: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 112
112: def initialize_guestfs(options = {})
113: @log.debug "Preparing guestfs..."
114: @log.trace "Setting libguestfs temporary directory to '#{@config.dir.tmp}'..."
115:
116: FileUtils.mkdir_p(@config.dir.tmp)
117: ENV['TMPDIR'] = @config.dir.tmp
118:
119: @guestfs = Guestfs::create
120:
121: if @guestfs.respond_to?(:set_event_callback)
122: @log.trace "We have event callbacks available!"
123: log_callback { prepare_guestfs(options) { yield } }
124: else
125: @log.trace "We don't have event callbacks available :( Falling back to proxy."
126: log_hack { prepare_guestfs(options) { yield } }
127: end
128: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 210
210: def load_selinux_policy
211: return unless @guestfs.exists('/etc/sysconfig/selinux') != 0
212:
213: @log.trace "Loading SElinux policy..."
214:
215: @guestfs.aug_init("/", 32)
216: @guestfs.aug_rm("/augeas/load//incl[. != '/etc/sysconfig/selinux']")
217: @guestfs.aug_load
218:
219: selinux = @guestfs.aug_get("/files/etc/sysconfig/selinux/SELINUX")
220:
221: begin
222: @guestfs.sh("/usr/sbin/load_policy") if !selinux.nil? and !selinux.eql?('disabled')
223: @log.trace "SElinux policy loaded."
224: rescue
225: @log.warn "Loading SELinux policy failed. SELinux may be not fully initialized."
226: ensure
227: @guestfs.aug_close
228: end
229: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 210
210: def load_selinux_policy
211: return unless @guestfs.exists('/etc/sysconfig/selinux') != 0
212:
213: @log.trace "Loading SElinux policy..."
214:
215: @guestfs.aug_init("/", 32)
216: @guestfs.aug_rm("/augeas/load//incl[. != '/etc/sysconfig/selinux']")
217: @guestfs.aug_load
218:
219: selinux = @guestfs.aug_get("/files/etc/sysconfig/selinux/SELINUX")
220:
221: begin
222: @guestfs.sh("/usr/sbin/load_policy") if !selinux.nil? and !selinux.eql?('disabled')
223: @log.trace "SElinux policy loaded."
224: rescue
225: @log.warn "Loading SELinux policy failed. SELinux may be not fully initialized."
226: ensure
227: @guestfs.aug_close
228: end
229: end
issues.jboss.org/browse/BGBUILD-83
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 59
59: def log_callback
60: default_callback = Proc.new do |event, event_handle, buf, array|
61: buf.chomp!
62:
63: if event == 64
64: @log.debug "GFS: #{buf}"
65: else
66: @log.trace "GFS: #{buf}" unless buf.start_with?('recv_from_daemon', 'send_to_daemon')
67: end
68: end
69:
70: # Guestfs::EVENT_APPLIANCE => 16
71: # Guestfs::EVENT_LIBRARY => 32
72: # Guestfs::EVENT_TRACE => 64
73:
74: # Referencing int instead of constants make it easier to test
75: @guestfs.set_event_callback(default_callback, 16 | 32 | 64)
76:
77: yield if block_given?
78: end
issues.jboss.org/browse/BGBUILD-83
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 59
59: def log_callback
60: default_callback = Proc.new do |event, event_handle, buf, array|
61: buf.chomp!
62:
63: if event == 64
64: @log.debug "GFS: #{buf}"
65: else
66: @log.trace "GFS: #{buf}" unless buf.start_with?('recv_from_daemon', 'send_to_daemon')
67: end
68: end
69:
70: # Guestfs::EVENT_APPLIANCE => 16
71: # Guestfs::EVENT_LIBRARY => 32
72: # Guestfs::EVENT_TRACE => 64
73:
74: # Referencing int instead of constants make it easier to test
75: @guestfs.set_event_callback(default_callback, 16 | 32 | 64)
76:
77: yield if block_given?
78: end
If log callback aren‘t available we will fail to this, which sucks…
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 81
81: def log_hack
82: read_stderr, write_stderr = IO.pipe
83:
84: fork do
85: write_stderr.close
86:
87: read_stderr.each do |l|
88: @log.trace "GFS: #{l.chomp.strip}"
89: end
90:
91: read_stderr.close
92: end
93:
94: old_stderr = STDERR.clone
95:
96: STDERR.reopen(write_stderr)
97: STDERR.sync = true
98:
99: begin
100: # Execute all tasks
101: yield if block_given?
102: ensure
103: STDERR.reopen(old_stderr)
104: end
105:
106: write_stderr.close
107: read_stderr.close
108:
109: Process.wait
110: end
If log callback aren‘t available we will fail to this, which sucks…
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 81
81: def log_hack
82: read_stderr, write_stderr = IO.pipe
83:
84: fork do
85: write_stderr.close
86:
87: read_stderr.each do |l|
88: @log.trace "GFS: #{l.chomp.strip}"
89: end
90:
91: read_stderr.close
92: end
93:
94: old_stderr = STDERR.clone
95:
96: STDERR.reopen(write_stderr)
97: STDERR.sync = true
98:
99: begin
100: # Execute all tasks
101: yield if block_given?
102: ensure
103: STDERR.reopen(old_stderr)
104: end
105:
106: write_stderr.close
107: read_stderr.close
108:
109: Process.wait
110: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 241
241: def mount_partition(part, mount_point, mount_prefix = '')
242: @log.trace "Mounting #{part} partition to #{mount_point}..."
243: @guestfs.mount_options("", part, "#{mount_prefix}#{mount_point}")
244: # By the way - update the labels so we don't have to muck again with partitions
245: # this will be done for every mount, but shouldn't hurt too much.
246: @guestfs.set_e2label(part, Zlib.crc32(mount_point).to_s(16))
247: @log.trace "Partition mounted."
248: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 241
241: def mount_partition(part, mount_point, mount_prefix = '')
242: @log.trace "Mounting #{part} partition to #{mount_point}..."
243: @guestfs.mount_options("", part, "#{mount_prefix}#{mount_point}")
244: # By the way - update the labels so we don't have to muck again with partitions
245: # this will be done for every mount, but shouldn't hurt too much.
246: @guestfs.set_e2label(part, Zlib.crc32(mount_point).to_s(16))
247: @log.trace "Partition mounted."
248: end
This mount partitions. We assume that the first partition is a root partition.
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 252
252: def mount_partitions(device, mount_prefix = '')
253: @log.trace "Mounting partitions..."
254:
255: partitions = mountable_partitions(device)
256: mount_points = LinuxHelper.new(:log => @log).partition_mount_points(@appliance_config.hardware.partitions)
257: # https://issues.jboss.org/browse/BGBUILD-307
258: # We don't want to mount swap partitions at all...
259: mount_points.delete("swap")
260: partitions.each_index { |i| mount_partition(partitions[i], mount_points[i], mount_prefix) }
261: end
This mount partitions. We assume that the first partition is a root partition.
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 252
252: def mount_partitions(device, mount_prefix = '')
253: @log.trace "Mounting partitions..."
254:
255: partitions = mountable_partitions(device)
256: mount_points = LinuxHelper.new(:log => @log).partition_mount_points(@appliance_config.hardware.partitions)
257: # https://issues.jboss.org/browse/BGBUILD-307
258: # We don't want to mount swap partitions at all...
259: mount_points.delete("swap")
260: partitions.each_index { |i| mount_partition(partitions[i], mount_points[i], mount_prefix) }
261: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 263
263: def mountable_partitions(device, options = {})
264: options = {:list_swap => false}.merge(options)
265:
266: partitions = @guestfs.list_partitions
267:
268: # we need to remove extended partition
269: # extended partition is always #3
270: partitions.delete_at(3) if partitions.size > 4
271:
272: partitions.reject { |i| !(i =~ /^#{device}/) or (@guestfs.vfs_type(i) == 'swap' and !options[:list_swap]) }
273: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 263
263: def mountable_partitions(device, options = {})
264: options = {:list_swap => false}.merge(options)
265:
266: partitions = @guestfs.list_partitions
267:
268: # we need to remove extended partition
269: # extended partition is always #3
270: partitions.delete_at(3) if partitions.size > 4
271:
272: partitions.reject { |i| !(i =~ /^#{device}/) or (@guestfs.vfs_type(i) == 'swap' and !options[:list_swap]) }
273: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 130
130: def prepare_guestfs(options = {})
131: @log.trace "Setting debug + trace..."
132: @guestfs.set_verbose(1)
133: @guestfs.set_trace(1)
134:
135: # https://issues.jboss.org/browse/BGBUILD-246
136: memsize = ENV['LIBGUESTFS_MEMSIZE'].nil? ? 300 : ENV['LIBGUESTFS_MEMSIZE'].to_i
137: @guestfs.set_memsize(memsize)
138:
139: # https://bugzilla.redhat.com/show_bug.cgi?id=502058
140: @guestfs.set_append("noapic")
141:
142: @log.trace "Enabling SElinux support in guestfs..."
143: @guestfs.set_selinux(1)
144:
145: unless hw_virtualization_available?
146: # This wrapper is required especially for EC2 where running qemu-kvm crashes libguestfs
147: qemu_wrapper = "#{File.dirname(__FILE__)}/qemu.wrapper"
148:
149: @log.trace "Setting QEMU wrapper to #{qemu_wrapper}..."
150: @guestfs.set_qemu(qemu_wrapper)
151: @log.trace "QEMU wrapper set."
152: end
153:
154: @disks.each do |disk|
155: @log.trace "Adding drive '#{disk}'..."
156: if options[:ide_disk]
157: @guestfs.add_drive_with_if(disk, 'ide')
158: else
159: @guestfs.add_drive(disk)
160: end
161: @log.trace "Drive added."
162: end
163:
164: if @guestfs.respond_to?('set_network')
165: @log.debug "Enabling networking for GuestFS..."
166: @guestfs.set_network(1)
167: end
168:
169: yield
170: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 130
130: def prepare_guestfs(options = {})
131: @log.trace "Setting debug + trace..."
132: @guestfs.set_verbose(1)
133: @guestfs.set_trace(1)
134:
135: # https://issues.jboss.org/browse/BGBUILD-246
136: memsize = ENV['LIBGUESTFS_MEMSIZE'].nil? ? 300 : ENV['LIBGUESTFS_MEMSIZE'].to_i
137: @guestfs.set_memsize(memsize)
138:
139: # https://bugzilla.redhat.com/show_bug.cgi?id=502058
140: @guestfs.set_append("noapic")
141:
142: @log.trace "Enabling SElinux support in guestfs..."
143: @guestfs.set_selinux(1)
144:
145: unless hw_virtualization_available?
146: # This wrapper is required especially for EC2 where running qemu-kvm crashes libguestfs
147: qemu_wrapper = "#{File.dirname(__FILE__)}/qemu.wrapper"
148:
149: @log.trace "Setting QEMU wrapper to #{qemu_wrapper}..."
150: @guestfs.set_qemu(qemu_wrapper)
151: @log.trace "QEMU wrapper set."
152: end
153:
154: @disks.each do |disk|
155: @log.trace "Adding drive '#{disk}'..."
156: if options[:ide_disk]
157: @guestfs.add_drive_with_if(disk, 'ide')
158: else
159: @guestfs.add_drive(disk)
160: end
161: @log.trace "Drive added."
162: end
163:
164: if @guestfs.respond_to?('set_network')
165: @log.debug "Enabling networking for GuestFS..."
166: @guestfs.set_network(1)
167: end
168:
169: yield
170: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 291
291: def sh(cmd, options = {})
292: arch = options[:arch] || `uname -m`.chomp.strip
293:
294: @log.debug "Executing '#{cmd}' command..."
295: @guestfs.sh("setarch #{arch} << 'SETARCH_EOF'\n#{cmd}\nSETARCH_EOF")
296: @log.debug "Command '#{cmd}' executed."
297: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 291
291: def sh(cmd, options = {})
292: arch = options[:arch] || `uname -m`.chomp.strip
293:
294: @log.debug "Executing '#{cmd}' command..."
295: @guestfs.sh("setarch #{arch} << 'SETARCH_EOF'\n#{cmd}\nSETARCH_EOF")
296: @log.debug "Command '#{cmd}' executed."
297: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 275
275: def umount_partition(part)
276: @log.trace "Unmounting partition #{part}..."
277: @guestfs.umount(part)
278: @log.trace "Partition unmounted."
279: end
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 275
275: def umount_partition(part)
276: @log.trace "Unmounting partition #{part}..."
277: @guestfs.umount(part)
278: @log.trace "Partition unmounted."
279: end
Unmounts partitions in reverse order.
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 283
283: def umount_partitions(device)
284: partitions = mountable_partitions(device)
285:
286: @log.trace "Unmounting partitions..."
287: partitions.reverse.each { |part| umount_partition(part) }
288: @log.trace "All partitions unmounted."
289: end
Unmounts partitions in reverse order.
# File lib/boxgrinder-build/helpers/guestfs-helper.rb, line 283
283: def umount_partitions(device)
284: partitions = mountable_partitions(device)
285:
286: @log.trace "Unmounting partitions..."
287: partitions.reverse.each { |part| umount_partition(part) }
288: @log.trace "All partitions unmounted."
289: end