Class: SystemBuilder::DiskImage

Inherits:
Object
  • Object
show all
Defined in:
lib/system_builder/disk_image.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file) ⇒ DiskImage

Returns a new instance of DiskImage.



8
9
10
11
# File 'lib/system_builder/disk_image.rb', line 8

def initialize(file)
  @file = file
  @size = 512.megabytes
end

Instance Attribute Details

#bootObject

Returns the value of attribute boot.



5
6
7
# File 'lib/system_builder/disk_image.rb', line 5

def boot
  @boot
end

#fileObject (readonly)

Returns the value of attribute file.



6
7
8
# File 'lib/system_builder/disk_image.rb', line 6

def file
  @file
end

#sizeObject

Returns the value of attribute size.



5
6
7
# File 'lib/system_builder/disk_image.rb', line 5

def size
  @size
end

Instance Method Details

#boot_fs_block_sizeObject



151
152
153
154
# File 'lib/system_builder/disk_image.rb', line 151

def boot_fs_block_size
  linux_partition_info = `/sbin/sfdisk -l #{file}`.scan(%r{#{file}.*W95 FAT32}).first
  linux_partition_info.split[5].to_i
end

#boot_fs_labelObject



168
169
170
# File 'lib/system_builder/disk_image.rb', line 168

def boot_fs_label
  "boot"
end

#boot_fs_offsetObject



147
148
149
# File 'lib/system_builder/disk_image.rb', line 147

def boot_fs_offset
  free_sectors * 512
end

#boot_fs_sector_countObject



156
157
158
# File 'lib/system_builder/disk_image.rb', line 156

def boot_fs_sector_count
  (120 * 1008) - free_sectors # end of partition on a multiple of 1008 (cylinder size)
end

#convert(export_file, options = {}) ⇒ Object



130
131
132
133
134
135
136
# File 'lib/system_builder/disk_image.rb', line 130

def convert(export_file, options = {})
  unless FileUtils.uptodate? export_file, file
    arguments = []
    arguments << "-O #{options[:format]}" if options[:format]
    FileUtils::sh "qemu-img convert -f raw #{file} #{arguments.join(' ')} #{export_file}"
  end
end

#createObject



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/system_builder/disk_image.rb', line 13

def create
  boot.create
  # TODO

  file_creation = (not File.exists?(file))
  if file_creation
    create_file
    create_partition_table

    format_boot_fs
    format_root_fs
  end

  install_syslinux_files

  sync_boot_fs
  sync_root_fs

  install_syslinux

  self
end

#create_fileObject



36
37
38
# File 'lib/system_builder/disk_image.rb', line 36

def create_file
  FileUtils::sh "dd if=/dev/zero of=#{file} count=#{size.in_megabytes.to_i} bs=1M"
end

#create_partition_tableObject



40
41
42
43
# File 'lib/system_builder/disk_image.rb', line 40

def create_partition_table
  # Partition must be bootable for syslinux
  FileUtils::sh "echo -e '#{free_sectors},#{boot_fs_sector_count},b,*\n#{boot_fs_sector_count+free_sectors},,L,' | /sbin/sfdisk --no-reread -uS -H16 -S63 #{file}"
end

#format_boot_fsObject



55
56
57
58
59
60
61
62
63
# File 'lib/system_builder/disk_image.rb', line 55

def format_boot_fs
  loop_device = "/dev/loop0"
  begin
    FileUtils::sudo "losetup -o #{boot_fs_offset} #{loop_device} #{file}"
    FileUtils::sudo "mkdosfs -v -F 32 -n #{boot_fs_label} #{loop_device} #{boot_fs_block_size}"
  ensure
    FileUtils::sudo "losetup -d #{loop_device}"
  end
end

#format_root_fsObject



45
46
47
48
49
50
51
52
53
# File 'lib/system_builder/disk_image.rb', line 45

def format_root_fs
  loop_device = "/dev/loop0"
  begin
    FileUtils::sudo "losetup -o #{root_fs_offset} #{loop_device} #{file}"
    FileUtils::sudo "mke2fs -L #{root_fs_label} -jqF #{loop_device} #{root_fs_block_size}"
  ensure
    FileUtils::sudo "losetup -d #{loop_device}"
  end
end

#free_sectorsObject



143
144
145
# File 'lib/system_builder/disk_image.rb', line 143

def free_sectors
  64
end

#install_syslinuxObject



125
126
127
128
# File 'lib/system_builder/disk_image.rb', line 125

def install_syslinux
  FileUtils::sh "syslinux -o #{boot_fs_offset} #{file}"
  FileUtils::sh "dd if=/usr/lib/syslinux/mbr.bin of=#{file} conv=notrunc"
end

#install_syslinux_files(options = {}) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/system_builder/disk_image.rb', line 105

def install_syslinux_files(options = {})
  root = (options[:root] or "LABEL=#{root_fs_label}")
  version = (options[:version] or Time.now.strftime("%Y%m%d%H%M"))

  boot.image do |image|
    image.mkdir "/boot/"

    image.open("/boot/syslinux.cfg") do |f|
      f.puts "default linux"
      f.puts "label linux"
      f.puts "kernel #{readlink_boot_file('vmlinuz')}"
      f.puts "append ro root=#{root} initrd=#{readlink_boot_file('initrd.img')} console=tty0 console=ttyS0"
    end
  end
end

#mount_boot_fs(&block) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/system_builder/disk_image.rb', line 78

def mount_boot_fs(&block)
  # TODO use a smarter mount_dir
  mount_dir = "/tmp/mount_boot_fs"
  FileUtils::mkdir_p mount_dir

  begin
    FileUtils::sudo "mount -o loop,offset=#{boot_fs_offset} #{file} #{mount_dir}"
    yield mount_dir
  ensure
    FileUtils::sudo "umount #{mount_dir}"
  end
end

#mount_root_fs(&block) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/system_builder/disk_image.rb', line 65

def mount_root_fs(&block)
  # TODO use a smarter mount_dir
  mount_dir = "/tmp/mount_root_fs"
  FileUtils::mkdir_p mount_dir

  begin
    FileUtils::sudo "mount -o loop,offset=#{root_fs_offset} #{file} #{mount_dir}"
    yield mount_dir
  ensure
    FileUtils::sudo "umount #{mount_dir}"
  end
end


121
122
123
# File 'lib/system_builder/disk_image.rb', line 121

def readlink_boot_file(boot_file)
  File.basename(%x{readlink #{boot.root}/#{boot_file}}.strip)
end

#root_fs_block_sizeObject



138
139
140
141
# File 'lib/system_builder/disk_image.rb', line 138

def root_fs_block_size
  linux_partition_info = `/sbin/sfdisk -l #{file}`.scan(%r{#{file}.*Linux}).first
  linux_partition_info.split[4].to_i
end

#root_fs_labelObject



164
165
166
# File 'lib/system_builder/disk_image.rb', line 164

def root_fs_label
  "root"
end

#root_fs_offsetObject



160
161
162
# File 'lib/system_builder/disk_image.rb', line 160

def root_fs_offset
  (free_sectors + boot_fs_sector_count) * 512
end

#sync_boot_fsObject



98
99
100
101
102
103
# File 'lib/system_builder/disk_image.rb', line 98

def sync_boot_fs
  mount_boot_fs do |mount_dir|
    FileUtils::sudo "rsync -a --delete #{boot.root}/boot/ #{mount_dir}"
  end
  FileUtils.touch file
end

#sync_root_fsObject



91
92
93
94
95
96
# File 'lib/system_builder/disk_image.rb', line 91

def sync_root_fs
  mount_root_fs do |mount_dir|
    FileUtils::sudo "rsync -a --delete --exclude='boot/**' --exclude='tmp/**' #{boot.root}/ #{mount_dir}"
  end
  FileUtils.touch file
end