Class: Macinbox::Actions::CreateHDDFromImage

Inherits:
Object
  • Object
show all
Defined in:
lib/macinbox/actions/create_hdd_from_image.rb

Instance Method Summary collapse

Constructor Details

#initialize(opts) ⇒ CreateHDDFromImage

Returns a new instance of CreateHDDFromImage.

Raises:



14
15
16
17
18
19
20
21
22
23
24
# File 'lib/macinbox/actions/create_hdd_from_image.rb', line 14

def initialize(opts)
  @input_image       = opts[:image_path]     or raise ArgumentError.new(":image_path not specified")
  @output_path       = opts[:hdd_path]       or raise ArgumentError.new(":hdd_path not specified")
  @parallels_app     = opts[:parallels_path] or raise ArgumentError.new(":parallels_path not specified")

  @collector         = opts[:collector]      or raise ArgumentError.new(":collector not specified")
  @debug             = opts[:debug]

  raise Macinbox::Error.new("input image not found")       unless File.exist? @input_image
  raise Macinbox::Error.new("Parallels Desktop not found") unless File.exist? @parallels_app
end

Instance Method Details

#runObject



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
# File 'lib/macinbox/actions/create_hdd_from_image.rb', line 26

def run
  @temp_dir = Task.backtick %W[ /usr/bin/mktemp -d -t create_hdd_from_image ]
  @collector.add_temp_dir @temp_dir

  Logger.info "Attaching the image..." do

    @collector.on_cleanup do
      %x( diskutil eject #{@device.shellescape} > /dev/null 2>&1 ) if @device
    end

    @device = %x(
      /usr/bin/hdiutil attach #{@input_image.shellescape} -nomount |
      /usr/bin/grep _partition_scheme |
      /usr/bin/cut -f1 |
      /usr/bin/tr -d [:space:]
    )

    raise Macinbox::Error.new("failed to attach the image") unless File.exist? @device
  end

  Logger.info "Converting the image to HDD format..." do

    disk_info = Task.backtick %W[ /usr/sbin/fdisk #{@device} ]

    geometry_re = /geometry: (\d+)\/(\d+)\/(\d+) \[(\d+) sectors\]/

    match = geometry_re.match(disk_info)

    raise Macinbox::Error.new("failed to determine disk geometry") if match.nil? || match.captures.length != 4

    device_sectors = match.captures[3]

    device_cylinders = match.captures[0]
    device_heads_per_track = match.captures[1]
    device_sectors_per_track = match.captures[2]

    bios_cylinders = 1024
    bios_heads_per_track = device_heads_per_track
    bios_sectors_per_track = device_sectors_per_track

    File.write "#{@temp_dir}/macinbox.vmdk", "      # Disk DescriptorFile\n      version=1\n      encoding=\"UTF-8\"\n      CID=fffffffe\n      parentCID=ffffffff\n      isNativeSnapshot=\"no\"\n      createType=\"monolithicFlat\"\n\n      # Extent description\n      RW \#{device_sectors} FLAT \"\#{@device}\" 0\n\n      # The Disk Data Base\n      #DDB\n\n      ddb.adapterType = \"lsilogic\"\n      ddb.deletable = \"true\"\n      ddb.geometry.biosCylinders = \"\#{bios_cylinders}\"\n      ddb.geometry.biosHeads = \"\#{bios_heads_per_track}\"\n      ddb.geometry.biosSectors = \"\#{bios_sectors_per_track}\"\n      ddb.geometry.cylinders = \"\#{device_cylinders}\"\n      ddb.geometry.heads = \"\#{device_heads_per_track}\"\n      ddb.geometry.sectors = \"\#{device_sectors_per_track}\"\n      ddb.longContentID = \"9fa218b506cfe68615c39994fffffffe\"\n      ddb.uuid = \"60 00 C2 99 91 76 dd 77-6e 0d 84 8b b0 24 6e 00\"\n      ddb.virtualHWVersion = \"14\"\n    EOF\n\n    prl_convert = \"\#{@parallels_app}/Contents/MacOS/prl_convert\"\n    task_opts = @debug ? {} : { :out => File::NULL }\n    Task.run %W[ \#{prl_convert} \#{@temp_dir}/macinbox.vmdk --allow-no-os --dst=\#{@temp_dir} ] + [task_opts]\n\n  end\n\n  Logger.info \"Moving the HDD to the destination...\" do\n    FileUtils.chown_R ENV[\"SUDO_USER\"], nil, \"\#{@temp_dir}/macinbox.hdd\"\n    FileUtils.mv \"\#{@temp_dir}/macinbox.hdd\", @output_path\n  end\n\n  Task.run %W[ /usr/sbin/diskutil eject \#{@device.shellescape} ]\n  @device = nil\n\nend\n"