Class: IgnitionDiskGenerator
- Inherits:
-
Object
- Object
- IgnitionDiskGenerator
- Defined in:
- lib/vagrant-ignition/action/IgnitionDiskGenerator.rb
Overview
Note: gpt and gpt2 are the primary and secondary headers respectively
Class Method Summary collapse
Class Method Details
.create_disk(ignition_name, config_drive) ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/vagrant-ignition/action/IgnitionDiskGenerator.rb', line 13 def self.create_disk(ignition_name, config_drive) # Constants @first_usable_lba = 2048 @gpt_entrysize = 128 @gpt_max_entries = 128 gpt_lba = 1 arr_lba = 2 lba_size = 512 pmbr_length = lba_size @gpt_length = lba_size arr_length = @gpt_max_entries * @gpt_entrysize minimum_disk_size = 1536000 # ~1.5M; there are issues with udev not registering the device if it is less than this... partitioner_reserved_space = (@first_usable_lba * lba_size) + (@gpt_length + arr_length) # this is space reserved by the partition tables and arrays part_label = "Ignition Config Drive" part_label_encoded = part_label.encode("utf-16le").bytes ignition_conf = File.open(ignition_name, "r") contents = ignition_conf.sysread(File.size?(ignition_name)) ignition_conf.close file_size_unrounded = contents.bytesize if file_size_unrounded < minimum_disk_size file_size = minimum_disk_size - partitioner_reserved_space elsif (file_size_unrounded % lba_size) != 0 file_size = lba_size * ((file_size_unrounded / lba_size) + 1) else file_size = file_size_unrounded end drive_size = file_size + partitioner_reserved_space # Calculated variables drive_sectors = drive_size / lba_size gpt2_lba = drive_sectors - 1 arr2_lba = drive_sectors - 33 # This is global as gen_gpt requires it @last_usable_lba = drive_sectors - 34 ## START PMBR ## pmbr = ("\0".bytes) * 446 # bootloader code pmbr += "\x00".bytes # status code pmbr += "\x00\x01\x00".bytes # first CHS (for a protective MBR, we can just use the min value) pmbr += "\xee".bytes # partition type pmbr += "\xfe\xff\xff".bytes # last CHS (for a protective MBR, we can just use the max value) pmbr += "\x01\x00\x00\x00".bytes # first LBA of first partition pmbr += [gpt2_lba].pack('L').bytes # last LBA of first partition pmbr += ("\x00".bytes) * 48 # other partition data pmbr += "\x55\xaa".bytes # MBR signature ## END PMBR ## ## START PART ## # UUID format on disk according to cgpt: # typedef struct { # UINT32 Data1; # UINT16 Data2; # UINT16 Data3; # UINT8 Data4[8]; # } EFI_GUID; # Partition Type GUID is 0FC63DAF-8483-4772-8E79-3D69D8477DE4 (Linux Filesystem) part1 = [0x0FC63DAF].pack('L').bytes + [0x8483].pack('S').bytes + [0x4772].pack('S').bytes + [0x8E793D69D8477DE4].pack('Q').bytes.reverse! # Partition GUID is 99570A8A-F826-4EB0-BA4E-9DD72D55EA13 part1 += [0x99570A8A].pack('L').bytes + [0xF826].pack('S').bytes + [0x4EB0].pack('S').bytes + [0xBA4E9DD72D55EA13].pack('Q').bytes.reverse! part1 += [@first_usable_lba].pack('Q').bytes # first LBA of first partition part1 += [@last_usable_lba].pack('Q').bytes # last LBA of first partition part1 += "\0".bytes * 8 # partition attributes part1 += part_label_encoded + ("\0".bytes * (72 - part_label_encoded.length)) # partition name (length of 72 bytes, or 36 utf16le characters) part_others = "\0".bytes * (arr_length - part1.length) # other partition data part_arr = part1 + part_others part_extra_space = "\0".bytes * ((@first_usable_lba * lba_size) - (pmbr_length + @gpt_length + arr_length)) # this adds a buffer so that our partition starts at sector 2048 part_full = part_arr + part_extra_space ## END PART ## ## START GPT ## gpt = gen_gpt(gpt_lba, gpt2_lba, arr_lba, part_arr) ## END GPT ## ## START GPT2 ## gpt2 = gen_gpt(gpt2_lba, gpt_lba, arr2_lba, part_arr) ## END GPT2 ## ## START DATA ## if file_size_unrounded < minimum_disk_size data = contents.bytes + ("\x00".bytes * (file_size - contents.bytesize)) else data = contents.bytes + ("\x00".bytes * (lba_size - (file_size_unrounded % lba_size))) end ## END DATA ## device = pmbr + gpt + part_full + data + part1 + part_others + gpt2 File.open(config_drive, 'wb' ) do |output| device.each do | byte | output.print byte.chr end end end |