manageiq-smartstate 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (305) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +4 -0
  4. data/.rspec_ci +4 -0
  5. data/.travis.yml +15 -0
  6. data/Gemfile +9 -0
  7. data/LICENSE.txt +202 -0
  8. data/README.md +45 -0
  9. data/Rakefile +23 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/lib/MiqContainerGroup/MiqContainerGroup.rb +31 -0
  13. data/lib/MiqVm/MiqLocalVm.rb +50 -0
  14. data/lib/MiqVm/MiqRhevmVm.rb +179 -0
  15. data/lib/MiqVm/MiqVm.rb +355 -0
  16. data/lib/MiqVm/miq_azure_vm.rb +96 -0
  17. data/lib/MiqVm/miq_scvmm_vm.rb +38 -0
  18. data/lib/MiqVm/test/camcorder_fleece_test.rb +60 -0
  19. data/lib/MiqVm/test/localVm.rb +45 -0
  20. data/lib/MiqVm/test/partitionAlignmentCheck.rb +76 -0
  21. data/lib/MiqVm/test/remoteVm.rb +65 -0
  22. data/lib/MiqVm/test/rhevmNfsTest.rb +62 -0
  23. data/lib/MiqVm/test/rhevmNfsTest2.rb +66 -0
  24. data/lib/MiqVm/test/rhevmTest.rb +70 -0
  25. data/lib/OpenStackExtract/MiqOpenStackVm/MiqOpenStackCommon.rb +107 -0
  26. data/lib/OpenStackExtract/MiqOpenStackVm/MiqOpenStackImage.rb +67 -0
  27. data/lib/OpenStackExtract/MiqOpenStackVm/MiqOpenStackInstance.rb +182 -0
  28. data/lib/Scvmm/miq_hyperv_disk.rb +273 -0
  29. data/lib/Scvmm/miq_scvmm_parse_powershell.rb +75 -0
  30. data/lib/Scvmm/miq_scvmm_vm_ssa_info.rb +135 -0
  31. data/lib/Scvmm/test/miq_hyperv_disk_test.rb +33 -0
  32. data/lib/Scvmm/test/miq_scvmm_vm_ssa_info_test.rb +41 -0
  33. data/lib/VmLocalDiskAccess/test/localCfg.rb +97 -0
  34. data/lib/VolumeManager/LVM/logical_volume.rb +75 -0
  35. data/lib/VolumeManager/LVM/lv_segment.rb +43 -0
  36. data/lib/VolumeManager/LVM/lvm2disk.rb +158 -0
  37. data/lib/VolumeManager/LVM/parser.rb +138 -0
  38. data/lib/VolumeManager/LVM/physical_volume.rb +19 -0
  39. data/lib/VolumeManager/LVM/scanner.rb +156 -0
  40. data/lib/VolumeManager/LVM/thin/btree.rb +83 -0
  41. data/lib/VolumeManager/LVM/thin/constants.rb +86 -0
  42. data/lib/VolumeManager/LVM/thin/data_map.rb +44 -0
  43. data/lib/VolumeManager/LVM/thin/mapping_tree.rb +19 -0
  44. data/lib/VolumeManager/LVM/thin/space_maps.rb +58 -0
  45. data/lib/VolumeManager/LVM/thin/superblock.rb +136 -0
  46. data/lib/VolumeManager/LVM/thin.rb +6 -0
  47. data/lib/VolumeManager/LVM/volume_group.rb +97 -0
  48. data/lib/VolumeManager/LVM.rb +8 -0
  49. data/lib/VolumeManager/MiqLdm.rb +546 -0
  50. data/lib/VolumeManager/MiqLvm.rb +17 -0
  51. data/lib/VolumeManager/MiqNativeVolumeManager.rb +150 -0
  52. data/lib/VolumeManager/MiqVolumeManager.rb +277 -0
  53. data/lib/VolumeManager/VolMgrPlatformSupport.rb +18 -0
  54. data/lib/VolumeManager/VolMgrPlatformSupportLinux.rb +77 -0
  55. data/lib/VolumeManager/VolMgrPlatformSupportWin.rb +17 -0
  56. data/lib/VolumeManager/test/blockDevTest.rb +40 -0
  57. data/lib/VolumeManager/test/ldm.rb +97 -0
  58. data/lib/blackbox/VmBlackBox.rb +103 -0
  59. data/lib/blackbox/xmlStorage.rb +180 -0
  60. data/lib/db/MiqBdb/MiqBdb.rb +309 -0
  61. data/lib/db/MiqBdb/MiqBdbBtree.rb +219 -0
  62. data/lib/db/MiqBdb/MiqBdbHash.rb +199 -0
  63. data/lib/db/MiqBdb/MiqBdbPage.rb +159 -0
  64. data/lib/db/MiqBdb/MiqBdbUtil.rb +18 -0
  65. data/lib/db/MiqSqlite/MiqSqlite3.rb +330 -0
  66. data/lib/db/MiqSqlite/MiqSqlite3Cell.rb +167 -0
  67. data/lib/db/MiqSqlite/MiqSqlite3Page.rb +151 -0
  68. data/lib/db/MiqSqlite/MiqSqlite3Table.rb +124 -0
  69. data/lib/db/MiqSqlite/MiqSqlite3Util.rb +32 -0
  70. data/lib/disk/DiskProbe.rb +68 -0
  71. data/lib/disk/MiqDisk.rb +317 -0
  72. data/lib/disk/camcorder_test.rb +90 -0
  73. data/lib/disk/dos_mbr.img +0 -0
  74. data/lib/disk/modules/AzureBlobDisk.rb +101 -0
  75. data/lib/disk/modules/LocalDevMod.rb +47 -0
  76. data/lib/disk/modules/LocalDevProbe.rb +6 -0
  77. data/lib/disk/modules/MSCommon.rb +352 -0
  78. data/lib/disk/modules/MSVSDiffDisk.rb +91 -0
  79. data/lib/disk/modules/MSVSDiskProbe.rb +61 -0
  80. data/lib/disk/modules/MSVSDynamicDisk.rb +42 -0
  81. data/lib/disk/modules/MSVSFixedDisk.rb +45 -0
  82. data/lib/disk/modules/MiqLargeFile.rb +63 -0
  83. data/lib/disk/modules/MiqLargeFileWin32.rb +107 -0
  84. data/lib/disk/modules/QcowDisk.rb +692 -0
  85. data/lib/disk/modules/QcowDiskProbe.rb +34 -0
  86. data/lib/disk/modules/RawBlockIO.rb +116 -0
  87. data/lib/disk/modules/RawDisk.rb +45 -0
  88. data/lib/disk/modules/RawDiskProbe.rb +7 -0
  89. data/lib/disk/modules/RhevmDescriptor.rb +167 -0
  90. data/lib/disk/modules/RhevmDiskProbe.rb +52 -0
  91. data/lib/disk/modules/VMWareCowdDisk.rb +207 -0
  92. data/lib/disk/modules/VMWareDescriptor.rb +214 -0
  93. data/lib/disk/modules/VMWareDiskProbe.rb +74 -0
  94. data/lib/disk/modules/VMWareSparseDisk.rb +189 -0
  95. data/lib/disk/modules/VhdxDisk.rb +625 -0
  96. data/lib/disk/modules/VhdxDiskProbe.rb +46 -0
  97. data/lib/disk/modules/VixDiskMod.rb +54 -0
  98. data/lib/disk/modules/VixDiskProbe.rb +6 -0
  99. data/lib/disk/modules/miq_disk_cache.rb +135 -0
  100. data/lib/disk/modules/miq_dummy_disk.rb +41 -0
  101. data/lib/disk/modules/vhdx_bat_entry.rb +10 -0
  102. data/lib/disk/test.rb +66 -0
  103. data/lib/fs/MetakitFS/MetakitFS.rb +530 -0
  104. data/lib/fs/MetakitFS/test/Makefile +14 -0
  105. data/lib/fs/MetakitFS/test/MkCollectFiles.rb +165 -0
  106. data/lib/fs/MetakitFS/test/MkSelectFiles.rb +30 -0
  107. data/lib/fs/MetakitFS/test/collect_files.yaml +70 -0
  108. data/lib/fs/MetakitFS/test/init.rb +3 -0
  109. data/lib/fs/MetakitFS/test/mk2vmdk.rb +64 -0
  110. data/lib/fs/MetakitFS/test/mk4test.c +92 -0
  111. data/lib/fs/MetakitFS/test/mkFsTest.rb +113 -0
  112. data/lib/fs/MetakitFS/test/proto.rb +97 -0
  113. data/lib/fs/MiqFS/FsProbe.rb +39 -0
  114. data/lib/fs/MiqFS/MiqFS.rb +515 -0
  115. data/lib/fs/MiqFS/modules/AUFSProbe.rb +26 -0
  116. data/lib/fs/MiqFS/modules/Ext3.rb +305 -0
  117. data/lib/fs/MiqFS/modules/Ext3Probe.rb +25 -0
  118. data/lib/fs/MiqFS/modules/Ext4.rb +304 -0
  119. data/lib/fs/MiqFS/modules/Ext4Probe.rb +25 -0
  120. data/lib/fs/MiqFS/modules/Fat32.rb +318 -0
  121. data/lib/fs/MiqFS/modules/Fat32Probe.rb +30 -0
  122. data/lib/fs/MiqFS/modules/HFSProbe.rb +18 -0
  123. data/lib/fs/MiqFS/modules/Iso9660.rb +293 -0
  124. data/lib/fs/MiqFS/modules/Iso9660Probe.rb +18 -0
  125. data/lib/fs/MiqFS/modules/LocalFS.rb +105 -0
  126. data/lib/fs/MiqFS/modules/NTFS.rb +287 -0
  127. data/lib/fs/MiqFS/modules/NTFSProbe.rb +21 -0
  128. data/lib/fs/MiqFS/modules/NativeFS.rb +155 -0
  129. data/lib/fs/MiqFS/modules/ReFSProbe.rb +17 -0
  130. data/lib/fs/MiqFS/modules/RealFS.rb +79 -0
  131. data/lib/fs/MiqFS/modules/RealFSProbe.rb +6 -0
  132. data/lib/fs/MiqFS/modules/Reiser4Probe.rb +18 -0
  133. data/lib/fs/MiqFS/modules/ReiserFS.rb +315 -0
  134. data/lib/fs/MiqFS/modules/ReiserFSProbe.rb +42 -0
  135. data/lib/fs/MiqFS/modules/UnionFSProbe.rb +18 -0
  136. data/lib/fs/MiqFS/modules/WebDAV.rb +127 -0
  137. data/lib/fs/MiqFS/modules/WebDAVFile.rb +68 -0
  138. data/lib/fs/MiqFS/modules/XFS.rb +300 -0
  139. data/lib/fs/MiqFS/modules/XFSProbe.rb +26 -0
  140. data/lib/fs/MiqFS/modules/ZFSProbe.rb +18 -0
  141. data/lib/fs/MiqFS/test.rb +59 -0
  142. data/lib/fs/MiqFsUtil.rb +383 -0
  143. data/lib/fs/MiqMountManager.rb +209 -0
  144. data/lib/fs/MiqNativeMountManager.rb +101 -0
  145. data/lib/fs/MountManagerProbe.rb +29 -0
  146. data/lib/fs/ReiserFS/block.rb +209 -0
  147. data/lib/fs/ReiserFS/directory.rb +136 -0
  148. data/lib/fs/ReiserFS/directory_entry.rb +140 -0
  149. data/lib/fs/ReiserFS/file_data.rb +111 -0
  150. data/lib/fs/ReiserFS/superblock.rb +140 -0
  151. data/lib/fs/ReiserFS/utils.rb +95 -0
  152. data/lib/fs/VimDatastoreFS/VimDatastoreFS.rb +192 -0
  153. data/lib/fs/ext3/alloc_bitmap.rb +38 -0
  154. data/lib/fs/ext3/block_pointers_path.rb +130 -0
  155. data/lib/fs/ext3/directory.rb +51 -0
  156. data/lib/fs/ext3/directory_entry.rb +67 -0
  157. data/lib/fs/ext3/ex_attrib_header.rb +14 -0
  158. data/lib/fs/ext3/ex_attrib_name.rb +23 -0
  159. data/lib/fs/ext3/file_data.rb +130 -0
  160. data/lib/fs/ext3/group_descriptor_entry.rb +65 -0
  161. data/lib/fs/ext3/group_descriptor_table.rb +54 -0
  162. data/lib/fs/ext3/hash_tree_entry.rb +18 -0
  163. data/lib/fs/ext3/hash_tree_header.rb +15 -0
  164. data/lib/fs/ext3/inode.rb +228 -0
  165. data/lib/fs/ext3/posix_acl_entry.rb +29 -0
  166. data/lib/fs/ext3/posix_acl_header.rb +11 -0
  167. data/lib/fs/ext3/superblock.rb +406 -0
  168. data/lib/fs/ext3/test/tc_Ext3BlockPointersPath.rb +74 -0
  169. data/lib/fs/ext4/alloc_bitmap.rb +38 -0
  170. data/lib/fs/ext4/directory.rb +87 -0
  171. data/lib/fs/ext4/directory_entry.rb +77 -0
  172. data/lib/fs/ext4/ex_attrib_header.rb +14 -0
  173. data/lib/fs/ext4/ex_attrib_name.rb +23 -0
  174. data/lib/fs/ext4/extent.rb +35 -0
  175. data/lib/fs/ext4/extent_header.rb +40 -0
  176. data/lib/fs/ext4/extent_index.rb +33 -0
  177. data/lib/fs/ext4/group_descriptor_entry.rb +69 -0
  178. data/lib/fs/ext4/group_descriptor_table.rb +54 -0
  179. data/lib/fs/ext4/hash_tree_entry.rb +58 -0
  180. data/lib/fs/ext4/hash_tree_header.rb +35 -0
  181. data/lib/fs/ext4/inode.rb +465 -0
  182. data/lib/fs/ext4/posix_acl_entry.rb +29 -0
  183. data/lib/fs/ext4/posix_acl_header.rb +11 -0
  184. data/lib/fs/ext4/superblock.rb +412 -0
  185. data/lib/fs/fat32/boot_sect.rb +379 -0
  186. data/lib/fs/fat32/directory.rb +222 -0
  187. data/lib/fs/fat32/directory_entry.rb +540 -0
  188. data/lib/fs/fat32/file_data.rb +128 -0
  189. data/lib/fs/iso9660/boot_sector.rb +170 -0
  190. data/lib/fs/iso9660/directory.rb +90 -0
  191. data/lib/fs/iso9660/directory_entry.rb +147 -0
  192. data/lib/fs/iso9660/file_data.rb +78 -0
  193. data/lib/fs/iso9660/rock_ridge.rb +329 -0
  194. data/lib/fs/iso9660/util.rb +57 -0
  195. data/lib/fs/modules/LinuxMount.rb +300 -0
  196. data/lib/fs/modules/LinuxMountProbe.rb +29 -0
  197. data/lib/fs/modules/WinMount.rb +97 -0
  198. data/lib/fs/modules/WinMountProbe.rb +24 -0
  199. data/lib/fs/ntfs/attrib_attribute_list.rb +131 -0
  200. data/lib/fs/ntfs/attrib_bitmap.rb +26 -0
  201. data/lib/fs/ntfs/attrib_data.rb +74 -0
  202. data/lib/fs/ntfs/attrib_file_name.rb +110 -0
  203. data/lib/fs/ntfs/attrib_header.rb +194 -0
  204. data/lib/fs/ntfs/attrib_index_allocation.rb +19 -0
  205. data/lib/fs/ntfs/attrib_index_root.rb +247 -0
  206. data/lib/fs/ntfs/attrib_object_id.rb +40 -0
  207. data/lib/fs/ntfs/attrib_standard_information.rb +107 -0
  208. data/lib/fs/ntfs/attrib_type.rb +49 -0
  209. data/lib/fs/ntfs/attrib_volume_information.rb +53 -0
  210. data/lib/fs/ntfs/attrib_volume_name.rb +31 -0
  211. data/lib/fs/ntfs/boot_sect.rb +253 -0
  212. data/lib/fs/ntfs/data_run.rb +358 -0
  213. data/lib/fs/ntfs/directory_index_node.rb +114 -0
  214. data/lib/fs/ntfs/index_node_header.rb +69 -0
  215. data/lib/fs/ntfs/index_record_header.rb +85 -0
  216. data/lib/fs/ntfs/mft_entry.rb +288 -0
  217. data/lib/fs/ntfs/utils.rb +43 -0
  218. data/lib/fs/test/camcorder_fs_test.rb +108 -0
  219. data/lib/fs/test/collect_files_direct.yaml +22 -0
  220. data/lib/fs/test/collect_files_in.yaml +24 -0
  221. data/lib/fs/test/collect_files_in_nc.yaml +22 -0
  222. data/lib/fs/test/collect_files_out.yaml +6 -0
  223. data/lib/fs/test/collect_files_rm.yaml +6 -0
  224. data/lib/fs/test/copyTest.rb +126 -0
  225. data/lib/fs/test/fsTest.rb +87 -0
  226. data/lib/fs/test/updateTest.rb +184 -0
  227. data/lib/fs/xfs/allocation_group.rb +160 -0
  228. data/lib/fs/xfs/bmap_btree_block.rb +125 -0
  229. data/lib/fs/xfs/bmap_btree_record.rb +80 -0
  230. data/lib/fs/xfs/bmap_btree_root_node.rb +72 -0
  231. data/lib/fs/xfs/directory.rb +133 -0
  232. data/lib/fs/xfs/directory2_data_header.rb +27 -0
  233. data/lib/fs/xfs/directory3_data_header.rb +34 -0
  234. data/lib/fs/xfs/directory_block_tail.rb +22 -0
  235. data/lib/fs/xfs/directory_data_header.rb +46 -0
  236. data/lib/fs/xfs/directory_entry.rb +106 -0
  237. data/lib/fs/xfs/inode.rb +532 -0
  238. data/lib/fs/xfs/inode_map.rb +100 -0
  239. data/lib/fs/xfs/short_form_directory_entry.rb +91 -0
  240. data/lib/fs/xfs/short_form_header.rb +44 -0
  241. data/lib/fs/xfs/superblock.rb +556 -0
  242. data/lib/lib/tasks/azure.rake +52 -0
  243. data/lib/manageiq/smartstate/version.rb +5 -0
  244. data/lib/manageiq/smartstate.rb +7 -0
  245. data/lib/manageiq-smartstate.rb +1 -0
  246. data/lib/metadata/MIQExtract/MIQExtract.rb +297 -0
  247. data/lib/metadata/MIQExtract/test/extractTest.rb +41 -0
  248. data/lib/metadata/MIQExtract/test/full_extract_test.rb +68 -0
  249. data/lib/metadata/ScanProfile/HostScanItem.rb +4 -0
  250. data/lib/metadata/ScanProfile/HostScanProfile.rb +4 -0
  251. data/lib/metadata/ScanProfile/HostScanProfiles.rb +41 -0
  252. data/lib/metadata/ScanProfile/ScanItemBase.rb +63 -0
  253. data/lib/metadata/ScanProfile/ScanProfileBase.rb +51 -0
  254. data/lib/metadata/ScanProfile/ScanProfilesBase.rb +60 -0
  255. data/lib/metadata/ScanProfile/VmScanItem.rb +4 -0
  256. data/lib/metadata/ScanProfile/VmScanProfile.rb +4 -0
  257. data/lib/metadata/ScanProfile/VmScanProfiles.rb +38 -0
  258. data/lib/metadata/ScanProfile/modules/HostScanItemFile.rb +51 -0
  259. data/lib/metadata/ScanProfile/modules/HostScanItemNteventlog.rb +84 -0
  260. data/lib/metadata/ScanProfile/modules/VmScanItemFile.rb +39 -0
  261. data/lib/metadata/ScanProfile/modules/VmScanItemNteventlog.rb +34 -0
  262. data/lib/metadata/ScanProfile/modules/VmScanItemRegistry.rb +64 -0
  263. data/lib/metadata/VMMount/VMMount.rb +81 -0
  264. data/lib/metadata/VMMount/VMPlatformMount.rb +18 -0
  265. data/lib/metadata/VMMount/VMPlatformMountLinux.rb +75 -0
  266. data/lib/metadata/VMMount/VMPlatformMountWin.rb +13 -0
  267. data/lib/metadata/VmConfig/GetNativeCfg.rb +45 -0
  268. data/lib/metadata/VmConfig/VmConfig.rb +947 -0
  269. data/lib/metadata/VmConfig/cfgConfig.rb +45 -0
  270. data/lib/metadata/VmConfig/ovfConfig.rb +99 -0
  271. data/lib/metadata/VmConfig/test/GetVMwareCfgTest.rb +40 -0
  272. data/lib/metadata/VmConfig/vmcConfig.rb +116 -0
  273. data/lib/metadata/VmConfig/vmtxConfig.rb +4 -0
  274. data/lib/metadata/VmConfig/vmxConfig.rb +162 -0
  275. data/lib/metadata/VmConfig/xmlConfig.rb +79 -0
  276. data/lib/metadata/VmConfig/xmlMsHyperVConfig.rb +41 -0
  277. data/lib/metadata/linux/InitProcHash.rb +632 -0
  278. data/lib/metadata/linux/LinuxInitProcs.rb +142 -0
  279. data/lib/metadata/linux/LinuxOSInfo.rb +237 -0
  280. data/lib/metadata/linux/LinuxPackages.rb +209 -0
  281. data/lib/metadata/linux/LinuxSystemd.rb +130 -0
  282. data/lib/metadata/linux/LinuxUsers.rb +289 -0
  283. data/lib/metadata/linux/LinuxUtils.rb +197 -0
  284. data/lib/metadata/linux/MiqConaryPackages.rb +41 -0
  285. data/lib/metadata/linux/MiqRpmPackages.rb +160 -0
  286. data/lib/metadata/linux/test/Name +0 -0
  287. data/lib/metadata/linux/test/Packages +0 -0
  288. data/lib/metadata/linux/test/rpoTest.rb +5 -0
  289. data/lib/metadata/linux/test/tc_LinuxUtils.rb +4157 -0
  290. data/lib/metadata/util/event_log_filter.rb +61 -0
  291. data/lib/metadata/util/md5deep.rb +280 -0
  292. data/lib/metadata/util/win32/Win32Accounts.rb +764 -0
  293. data/lib/metadata/util/win32/Win32EventLog.rb +743 -0
  294. data/lib/metadata/util/win32/Win32Services.rb +86 -0
  295. data/lib/metadata/util/win32/Win32Software.rb +326 -0
  296. data/lib/metadata/util/win32/Win32System.rb +333 -0
  297. data/lib/metadata/util/win32/boot_info_win.rb +59 -0
  298. data/lib/metadata/util/win32/fleece_hives.rb +220 -0
  299. data/lib/metadata/util/win32/ms-registry.rb +650 -0
  300. data/lib/metadata/util/win32/peheader.rb +868 -0
  301. data/lib/metadata/util/win32/remote-registry.rb +142 -0
  302. data/lib/metadata/util/win32/system_path_win.rb +103 -0
  303. data/lib/metadata/util/win32/versioninfo.rb +17 -0
  304. data/manageiq-smartstate.gemspec +35 -0
  305. metadata +486 -0
@@ -0,0 +1,101 @@
1
+ require_relative "../MiqDisk"
2
+ require 'ostruct'
3
+
4
+ module AzureBlobDisk
5
+ # The maximum read length that supports MD5 return.
6
+ MAX_READ_LEN = 1024 * 1024 * 4
7
+
8
+ def self.new(svc, blob_uri, dInfo = nil)
9
+ d_info = dInfo || OpenStruct.new
10
+ d_info.storage_acct_svc = svc
11
+ d_info.blob_uri = blob_uri
12
+ d_info.fileName = blob_uri
13
+
14
+ MiqDisk.new(self, d_info, 0)
15
+ end
16
+
17
+ def d_init
18
+ @diskType = "azure-blob"
19
+ @blockSize = 512
20
+ @blob_uri = @dInfo.blob_uri
21
+ @storage_acct_svc = @dInfo.storage_acct_svc
22
+
23
+ uri_info = @storage_acct_svc.parse_uri(@blob_uri)
24
+ @container = uri_info[:container]
25
+ @blob = uri_info[:blob]
26
+ @acct_name = uri_info[:account_name]
27
+ @snapshot = uri_info[:snapshot]
28
+
29
+ @storage_acct = @storage_acct_svc.accounts_by_name[@acct_name]
30
+ raise "AzureBlob: Storage account #{@acct_name} not found." unless @storage_acct
31
+
32
+ $log.debug "AzureBlobDisk: open(#{@blob_uri})"
33
+ @t0 = Time.now.to_i
34
+ @reads = 0
35
+ @bytes = 0
36
+ @split_reads = 0
37
+ end
38
+
39
+ def d_close
40
+ return nil unless $log.debug?
41
+ t1 = Time.now.to_i
42
+ $log.debug "AzureBlobDisk: close(#{@blob_uri})"
43
+ $log.debug "AzureBlobDisk: (#{@blob_uri}) time: #{t1 - @t0}"
44
+ $log.debug "AzureBlobDisk: (#{@blob_uri}) reads: #{@reads}, split_reads: #{@split_reads}"
45
+ $log.debug "AzureBlobDisk: (#{@blob_uri}) bytes: #{@bytes}"
46
+ nil
47
+ end
48
+
49
+ def d_read(pos, len)
50
+ $log.debug "AzureBlobDisk#d_read(#{pos}, #{len})"
51
+ return blob_read(pos, len) unless len > MAX_READ_LEN
52
+
53
+ @split_reads += 1
54
+ ret = ""
55
+ blocks, rem = len.divmod(MAX_READ_LEN)
56
+
57
+ blocks.times do
58
+ ret << blob_read(pos, MAX_READ_LEN)
59
+ end
60
+ ret << blob_read(pos, rem) if rem > 0
61
+
62
+ ret
63
+ end
64
+
65
+ def d_size
66
+ @d_size ||= blob_properties[:content_length].to_i
67
+ end
68
+
69
+ def d_write(_pos, _buf, _len)
70
+ raise "Write operation not supported."
71
+ end
72
+
73
+ private
74
+
75
+ def blob_read(start_byte, length)
76
+ $log.debug "AzureBlobDisk#blob_read(#{start_byte}, #{length})"
77
+ options = {
78
+ :start_byte => start_byte,
79
+ :length => length
80
+ }
81
+ options[:date] = @snapshot if @snapshot
82
+
83
+ ret = @storage_acct.get_blob_raw(@container, @blob, key, options)
84
+
85
+ @reads += 1
86
+ @bytes += ret.body.length
87
+
88
+ ret.body
89
+ end
90
+
91
+ def blob_properties
92
+ @blob_properties ||= begin
93
+ options = @snapshot ? {:date => @snapshot} : {}
94
+ @storage_acct.blob_properties(@container, @blob, key, options)
95
+ end
96
+ end
97
+
98
+ def key
99
+ @key ||= @storage_acct_svc.list_account_keys(@storage_acct.name, @storage_acct.resource_group).fetch('key1')
100
+ end
101
+ end
@@ -0,0 +1,47 @@
1
+ require 'disk/modules/MiqLargeFile'
2
+
3
+ module LocalDevMod
4
+ attr_reader :devFile
5
+ attr_accessor :mkfile
6
+
7
+ def d_init
8
+ self.diskType = "LocalDev"
9
+ self.blockSize = 512
10
+ @mkfile = nil
11
+ dev = dInfo.localDev || dInfo.fileName
12
+ @devFile = dev
13
+ @devFile += @partNum.to_s if @partNum != 0
14
+
15
+ #
16
+ # Set fileName after the disk probe has determined that this is a local device.
17
+ # fileName can then be used as a common reference for debugging, etc.
18
+ #
19
+ dInfo.fileName = dev
20
+ dInfo.mountMode = "r"
21
+
22
+ @rawDisk_file = MiqLargeFile.open(dev, "r")
23
+ end
24
+
25
+ def getBase
26
+ self
27
+ end
28
+
29
+ def d_read(pos, len, offset = 0)
30
+ pos += @dInfo.offset if @dInfo.offset
31
+ @rawDisk_file.seek(pos - offset, IO::SEEK_SET)
32
+ @rawDisk_file.read(len)
33
+ end
34
+
35
+ def d_write(_pos, _buf, _len, _offset = 0)
36
+ raise "LocalDevMod: write not supported"
37
+ end
38
+
39
+ def d_close
40
+ @rawDisk_file.close
41
+ end
42
+
43
+ # Disk size in sectors.
44
+ def d_size
45
+ @rawDisk_file.size / @blockSize
46
+ end
47
+ end
@@ -0,0 +1,6 @@
1
+ module LocalDevProbe
2
+ def self.probe(ostruct)
3
+ return("LocalDevMod") if ostruct.localDev || File.blockdev?(ostruct.fileName)
4
+ (nil)
5
+ end
6
+ end
@@ -0,0 +1,352 @@
1
+ require 'disk/modules/MiqLargeFile'
2
+ require 'util/miq-unicode'
3
+ require 'binary_struct'
4
+ require 'memory_buffer'
5
+ require 'Scvmm/miq_hyperv_disk'
6
+
7
+ module MSCommon
8
+ # NOTE: All values are stored in network byte order.
9
+
10
+ FOOTER = BinaryStruct.new([
11
+ 'a8', 'cookie', # Always 'conectix'.
12
+ 'N', 'features', # Should be 2 or 3 (bit 0 is temp disk).
13
+ 'N', 'version', # Major/Minor file format version.
14
+ 'N', 'data_offset_hi', # Offset from beginning of file to next data struct (dyn & diff only, 0xffffffff for fixed).
15
+ 'N', 'data_offset_lo',
16
+ 'N', 'time_stamp', # Create time (sec since Jan 1 2000 12:00 AM in GMT).
17
+ 'a4', 'creator_app', # Virtual PC = 'vpc ', Virtual Server = 'vs '.
18
+ 'N', 'creator_ver', # Major/Minor ver of creator app.
19
+ 'N', 'creator_host', # Creator host: Windows = 0x5769326b ('Wi2k'); Macintosh = 0x4d616320 ('Mac ').
20
+ 'N', 'original_size_hi', # Original size of disk.
21
+ 'N', 'original_size_lo',
22
+ 'N', 'current_size_hi', # Current size of the disk.
23
+ 'N', 'current_size_lo',
24
+ 'N', 'disk_geometry', # CHS (byte sizes 2, 1, 1) values for disk.
25
+ 'N', 'disk_type', # Disk subtype (Fixed, Dynamic or Differencing).
26
+ 'N', 'checksum', # One's compliment of sum of struct minus this field.
27
+ 'a16', 'unique_id', # UUID.
28
+ 'C', 'saved_state', # If 1, system is in 'saved state'.
29
+ ])
30
+
31
+ HEADER = BinaryStruct.new([
32
+ 'a8', 'cookie', # Always 'cxsparse'.
33
+ 'Q', 'data_offset', # Unused, should be 0xffffffff.
34
+ 'N', 'table_offset_hi', # Byte offset to the Block Allocation Table.
35
+ 'N', 'table_offset_lo',
36
+ 'N', 'header_ver', # Major/Minor header version.
37
+ 'N', 'max_tbl_ent', # Max entries in the BAT.
38
+ 'N', 'block_size', # Size of data section of a block, default 2M (0x00200000).
39
+ 'N', 'checksum', # One's compliment sum of all fields minus this one.
40
+ 'a16', 'parent_uuid', # Parent disk UUID (for differencing disk only).
41
+ 'N', 'parent_tstamp', # MTime of parent disk (sec since Jan 1 2000 12:00 AM in GMT).
42
+ 'N', 'reserved1', # reserved, should be 0.
43
+ 'a512', 'parent_uname', # Parent disk filename in UNICODE (UTF-16).
44
+ 'a24', 'parent_loc1', # Parent locator entries.
45
+ 'a24', 'parent_loc2',
46
+ 'a24', 'parent_loc3',
47
+ 'a24', 'parent_loc4',
48
+ 'a24', 'parent_loc5',
49
+ 'a24', 'parent_loc6',
50
+ 'a24', 'parent_loc7',
51
+ 'a24', 'parent_loc8',
52
+ ])
53
+
54
+ PARENT_LOCATOR = BinaryStruct.new([
55
+ 'a4', 'platform_code', # Platform specific format used for locator.
56
+ 'N', 'data_space', # Number of sectors used to store locator.
57
+ 'N', 'data_length', # Byte length of locator.
58
+ 'N', 'reserved1', # Must be zero.
59
+ 'N', 'data_offset_hi', # Absolute byte offset of locator.
60
+ 'N', 'data_offset_lo',
61
+ ])
62
+
63
+ BAE_SIZE = 4
64
+ SECTOR_LENGTH = 512
65
+ FOOTER_LENGTH = 512
66
+ HEADER_LOCATION = 512
67
+ BLOCK_NOT_ALLOCATED = 0xffffffff
68
+ SUPPORTED_HEADER_VERSION = 0x00010000
69
+
70
+ def self.connect_to_hyperv(ostruct)
71
+ connection = ostruct.hyperv_connection
72
+ @network = ostruct.driveType == "Network"
73
+ hyperv_disk = MiqHyperVDisk.new(connection[:host],
74
+ connection[:user],
75
+ connection[:password],
76
+ connection[:port],
77
+ @network)
78
+ hyperv_disk.open(ostruct.fileName)
79
+ hyperv_disk
80
+ end
81
+
82
+ def self.d_init_common(dInfo, file)
83
+ @dInfo = dInfo
84
+ @blockSize = SECTOR_LENGTH
85
+ @file = file
86
+
87
+ # Get file, footer & header, do footer verification.
88
+ @footer = getFooter(@file, true)
89
+ @header = getHeader(@footer, true)
90
+ verifyFooterCopy(@footer)
91
+
92
+ # Verify footer copy.
93
+
94
+ # Verify format version number (must be 0x00010000).
95
+ raise "Incompatible header version: 0x#{'%04x' % @header['header_ver']}" if @header['header_ver'] != SUPPORTED_HEADER_VERSION
96
+
97
+ # Calc sectors per block, bytes in block sector bitmap & BAT loc.
98
+ @secPerBlock = @header['block_size'] / @blockSize
99
+ @blockSectorBitmapByteCount = @secPerBlock / 8
100
+ if (bd = @blockSectorBitmapByteCount % 512) != 0
101
+ @blockSectorBitmapByteCount = @blockSectorBitmapByteCount + 512 - bd
102
+ end
103
+ @batBase = getHiLo(@header, "table_offset")
104
+ process_bae
105
+ end
106
+
107
+ def self.d_read_common(pos, len, parent = nil)
108
+ # Get starting & ending block, sector & byte offset of read.
109
+ blockStart, sectorStart, byteOffsetStart = blockPos(pos)
110
+ blockEnd, sectorEnd, byteOffsetEnd = blockPos(pos + len - 1)
111
+
112
+ # Loop on blocks (2M entities of storage).
113
+ buf = ""
114
+ (blockStart..blockEnd).each do |blockNum|
115
+ # Loop on sectors (512 byte entities of storage).
116
+ secStart = (blockNum == blockStart) ? sectorStart : 0
117
+ secEnd = (blockNum == blockEnd) ? sectorEnd : @secPerBlock - 1
118
+ (secStart..secEnd).each do |secNum|
119
+ # If STARTING, need to skip to where data is
120
+ if (blockStart == blockEnd) && (sectorStart == sectorEnd)
121
+ byteOffset = byteOffsetStart
122
+ thisLen = len
123
+ elsif (blockNum == blockStart) && (secNum == sectorStart)
124
+ byteOffset = byteOffsetStart
125
+ thisLen = @blockSize - byteOffset
126
+ # If ENDING, need to account for short read
127
+ elsif (blockNum == blockEnd) && (secNum == sectorEnd)
128
+ byteOffset = 0
129
+ thisLen = len - buf.length
130
+ raise "Internal Error: Calculated read more than sector: #{thisLen}" if thisLen > @blockSize
131
+ # Read ENTIRE Sector in all other cases
132
+ else
133
+ byteOffset = 0
134
+ thisLen = @blockSize
135
+ end
136
+
137
+ # If the allocation status of this sector is 0 return zeros.
138
+ allocStat = getAllocStatus(blockNum, secNum)
139
+ if allocStat == false
140
+ if parent.nil?
141
+ buf << MemoryBuffer.create(thisLen)
142
+ else
143
+ buf << parent.d_read(pos + buf.length, thisLen)
144
+ end
145
+ else
146
+ @file.seek(getAbsSectorLoc(blockNum, secNum) + byteOffset, IO::SEEK_SET)
147
+ buf << @file.read(thisLen)
148
+ end
149
+ end
150
+ end
151
+ buf
152
+ end
153
+
154
+ def self.d_write_common(pos, buf, len, parent = nil)
155
+ # Get starting & ending block, sector & byte offset of read.
156
+ blockStart, sectorStart, byteOffsetStart = blockPos(pos)
157
+ blockEnd, sectorEnd, byteOffsetEnd = blockPos(pos + len - 1)
158
+
159
+ # Loop on blocks (2M entities of storage).
160
+ bytesWritten = 0
161
+ (blockStart..blockEnd).each do |blockNum|
162
+ # Loop on sectors (512 byte entities of storage).
163
+ secStart = (blockNum == blockStart) ? sectorStart : 0
164
+ secEnd = (blockNum == blockEnd) ? sectorEnd : @secPerBlock - 1
165
+ (secStart..secEnd).each do |secNum|
166
+ # If STARTING, need to skip to where data is
167
+ if (blockStart == blockEnd) && (sectorStart == sectorEnd)
168
+ byteOffset = byteOffsetStart
169
+ thisLen = len
170
+ elsif (blockNum == blockStart) && (secNum == sectorStart)
171
+ byteOffset = byteOffsetStart
172
+ thisLen = @blockSize - byteOffset
173
+ # If ENDING, need to account for short read
174
+ elsif (blockNum == blockEnd) && (secNum == sectorEnd)
175
+ byteOffset = 0
176
+ thisLen = len - bytesWritten
177
+ raise "Internal Error: Calculated read more than sector: #{thisLen}" if thisLen > @blockSize
178
+ # Read ENTIRE Sector in all other cases
179
+ else
180
+ byteOffset = 0
181
+ thisLen = @blockSize
182
+ end
183
+
184
+ # If the allocation status of this sector is 0 then allocate it.
185
+ allocStat = getAllocStatus(blockNum, secNum)
186
+ allocSector(blockNum, secNum, pos + bytesWritten, parent) if allocStat == false
187
+ @file.seek(getAbsSectorLoc(blockNum, secNum) + byteOffset, IO::SEEK_SET)
188
+ bytesWritten += @file.write(buf[bytesWritten, thisLen], thisLen)
189
+ end
190
+ end
191
+ bytesWritten
192
+ end
193
+
194
+ # Disk size in sectors.
195
+ def self.d_size_common
196
+ getHiLo(@footer, "current_size") / @blockSize
197
+ end
198
+
199
+ def self.getHiLo(hash, member)
200
+ (hash["#{member}_hi"] << 32) + hash["#{member}_lo"]
201
+ end
202
+
203
+ # Needed by diff disk.
204
+ def self.header
205
+ @header
206
+ end
207
+
208
+ def self.getFooter(file, skip_check = false)
209
+ # NOTE: Spec says that if checksum fails use the copy in the header.
210
+ # If that fails then the disk is corrupt.
211
+ file.seek(file.size - FOOTER_LENGTH, IO::SEEK_SET)
212
+ @footerBuf = file.read(FOOTER_LENGTH)
213
+ footer = FOOTER.decode(@footerBuf)
214
+ # TODO: Find out why this checksum test is failing. For now don't call getFooter without skip_check set to "true"
215
+ unless skip_check
216
+ footerCsum = checksum(@footerBuf, 64)
217
+ raise "Footer checksum doesn't match: got 0x#{'%04x' % footerCsum}, s/b 0x#{'%04x' % @footer['checksum']}" if footerCsum != footer['checksum']
218
+ end
219
+ footer
220
+ end
221
+
222
+ private
223
+
224
+ def self.getHeader(footer, skip_check = false)
225
+ hdrLoc = getHiLo(footer, "data_offset")
226
+ hdrSiz = HEADER.size
227
+ puts "VHD Header is mislocated: 0x#{'%04x' % hdrLoc} (s/b 0x0200)" if hdrLoc != HEADER_LOCATION && !skip_check
228
+ @file.seek(hdrLoc, IO::SEEK_SET)
229
+ buf = @file.read(hdrSiz)
230
+ header = HEADER.decode(buf)
231
+ # TODO: Find out why this checksum test is failing. For now don't call getHeader without skip_check set to "true"
232
+ unless skip_check
233
+ headerCsum = checksum(buf, 36)
234
+ raise "Header checksum doesn't match: got 0x#{'%04x' % headerCsum}, s/b 0x#{'%04x' % @header['checksum']}" if headerCsum != header['checksum']
235
+ end
236
+ header
237
+ end
238
+
239
+ def self.verifyFooterCopy(footer)
240
+ hdrLoc = getHiLo(footer, "data_offset")
241
+ @file.seek(hdrLoc - FOOTER_LENGTH, IO::SEEK_SET)
242
+ footer_copy = FOOTER.decode(@file.read(FOOTER_LENGTH))
243
+ puts "Footer copy does not match header." if footer_copy != @footer
244
+ end
245
+
246
+ def self.blockPos(pos)
247
+ rawSectorNumber, byteOffset = pos.divmod(@blockSize)
248
+ blockNumber, secInBlock = rawSectorNumber.divmod(@secPerBlock)
249
+ return blockNumber, secInBlock, byteOffset
250
+ end
251
+
252
+ def self.process_bae
253
+ @file.seek(@batBase, IO::SEEK_SET)
254
+ @bae = []
255
+ 1.step(@header['max_tbl_ent'], 1) do |block_num|
256
+ @bae << @file.read(BAE_SIZE).unpack('N')[0]
257
+ end
258
+ end
259
+
260
+ def self.getBAE(blockNumber)
261
+ @bae[blockNumber]
262
+ end
263
+
264
+ def self.putBAE(blockNum, bae)
265
+ seekBAE(blockNum)
266
+ @file.write([bae].pack('N'), BAE_SIZE)
267
+ end
268
+
269
+ def self.seekBAE(blockNum)
270
+ batOffset = blockNum * BAE_SIZE + @batBase
271
+ @file.seek(batOffset, IO::SEEK_SET)
272
+ end
273
+
274
+ def self.getAllocStatus(blockNum, sectorNum)
275
+ sectorMask = seekAllocStatus(blockNum, sectorNum)
276
+ return false if sectorMask == BLOCK_NOT_ALLOCATED
277
+ sectorBitmap = @file.read(1).unpack('C')[0]
278
+ sectorBitmap & sectorMask == sectorMask
279
+ end
280
+
281
+ def self.setAllocStatus(blockNum, sectorNum)
282
+ sectorMask = seekAllocStatus(blockNum, sectorNum)
283
+ sectorBitmap = @file.read(1).unpack('C')[0]
284
+ sectorBitmap |= sectorMask
285
+ @file.seek(-1, IO::SEEK_CUR)
286
+ @file.write([sectorBitmap].pack('C'), 1)
287
+ end
288
+
289
+ def self.seekAllocStatus(blockNum, sectorNum)
290
+ sectorByte, bitOffset = sectorNum.divmod(8)
291
+ bae = getBAE(blockNum)
292
+ return bae if bae == BLOCK_NOT_ALLOCATED
293
+ @file.seek(bae * @blockSize + sectorByte, IO::SEEK_SET)
294
+ 0x80 >> bitOffset
295
+ end
296
+
297
+ def self.getAbsSectorLoc(blockNum, sectorNum)
298
+ getBAE(blockNum) * @blockSize + sectorNum * @blockSize + @blockSectorBitmapByteCount
299
+ end
300
+
301
+ def self.allocSector(blockNum, sectorNum, pos, parent)
302
+ allocBlock(blockNum) if getBAE(blockNum) == BLOCK_NOT_ALLOCATED
303
+ if parent.nil?
304
+ buf = MemoryBuffer.create(@blockSize)
305
+ else
306
+ sector = pos.divmod(@blockSize)[0]
307
+ buf = parent.d_read(sector, @blockSize)
308
+ end
309
+ setAllocStatus(blockNum, sectorNum)
310
+ @file.seek(getAbsSectorLoc(blockNum, sectorNum), IO::SEEK_SET)
311
+ @file.write(buf, buf.size)
312
+ end
313
+
314
+ def self.allocBlock(blockNum)
315
+ # Alloc block.
316
+ pos = @file.size - FOOTER_LENGTH
317
+ sector = findFreeSector
318
+ putBAE(blockNum, sector)
319
+ # Write sector alloc bitmap.
320
+ bmp = MemoryBuffer.create(@blockSectorBitmapByteCount)
321
+ @file.seek(sector * @blockSize, IO::SEEK_SET)
322
+ @file.write(bmp, bmp.size)
323
+ # Footer has to move. Total size is 2048 + size of data blocks.
324
+ pos += @secPerBlock * @blockSize
325
+ @file.seek(pos, IO::SEEK_SET)
326
+ @file.write(@footerBuf, @footerBuf.size)
327
+ end
328
+
329
+ def self.findFreeSector
330
+ # Find a free disk sector with which to start a new block.
331
+ if @freeSector.nil?
332
+ seekBAE(0); ents = @header['max_tbl_ent']
333
+ baes = @file.read(ents * BAE_SIZE).unpack("N#{ents}")
334
+ baes.delete(BLOCK_NOT_ALLOCATED)
335
+ raise "Disk full." if baes.size == @header['max_tbl_ent']
336
+ @freeSector = baes.max
337
+ end
338
+ @freeSector += @secPerBlock
339
+ raise "Disk full." if @freeSector > d_size_common / @blockSize
340
+ @freeSector
341
+ end
342
+
343
+ def self.checksum(buf, skip_offset)
344
+ csum = 0
345
+ 0.upto(buf.size - 1) do|i|
346
+ next if i >= skip_offset && i < skip_offset + 4
347
+ csum += buf[i].to_i
348
+ end
349
+ # GRRRRR - convert to actual 32-bits.
350
+ [~csum].pack('L').unpack('L')[0]
351
+ end
352
+ end # module
@@ -0,0 +1,91 @@
1
+ # encoding: US-ASCII
2
+
3
+ require 'disk/modules/MSCommon'
4
+
5
+ module MSVSDiffDisk
6
+ def d_init
7
+ self.diskType = "MSVS Differencing"
8
+ self.blockSize = MSCommon::SECTOR_LENGTH
9
+ if dInfo.mountMode.nil? || dInfo.mountMode == "r"
10
+ dInfo.mountMode = "r"
11
+ fileMode = "r"
12
+ elsif dInfo.mountMode == "rw"
13
+ fileMode = "r+"
14
+ else
15
+ raise "Unrecognized mountMode: #{dInfo.mountMode}"
16
+ end
17
+ if dInfo.hyperv_connection
18
+ @hyperv_connection = dInfo.hyperv_connection
19
+ @ms_disk_file = MSCommon.connect_to_hyperv(dInfo)
20
+ else
21
+ @hyperv_connection = nil
22
+ @ms_disk_file = MiqLargeFile.open(dInfo.fileName, fileMode) unless dInfo.baseOnly
23
+ end
24
+ MSCommon.d_init_common(dInfo, @ms_disk_file) unless dInfo.baseOnly
25
+
26
+ # Get parent locators.
27
+ @locators = []
28
+ 1.upto(8) do|idx|
29
+ @locators << MSCommon::PARENT_LOCATOR.decode(MSCommon.header["parent_loc#{idx}"])
30
+ next if @locators[idx - 1]['platform_code'] == "\000\000\000\000"
31
+ locator = @locators[idx - 1]
32
+ if locator['platform_code'] == "W2ku"
33
+ getParentPathWin(locator)
34
+ getParent(locator)
35
+ end
36
+ end
37
+ raise "No compatible parent locator found" if @parent == nil
38
+ end
39
+
40
+ def getBase
41
+ @parent || self
42
+ end
43
+
44
+ # /////////////////////////////////////////////////////////////////////////
45
+ # Implementation.
46
+
47
+ def d_read(pos, len)
48
+ MSCommon.d_read_common(pos, len, @parent)
49
+ end
50
+
51
+ def d_write(pos, buf, len)
52
+ MSCommon.d_write_common(pos, buf, len, @parent)
53
+ end
54
+
55
+ def d_close
56
+ @parent.close if @parent
57
+ @ms_disk_file.close
58
+ end
59
+
60
+ def d_size
61
+ total = 0
62
+ total = @parent.d_size if @parent
63
+ total += @ms_disk_file.size
64
+ total
65
+ end
66
+
67
+ # /////////////////////////////////////////////////////////////////////////
68
+ # // Helpers.
69
+
70
+ private
71
+
72
+ def getParent(locator)
73
+ if locator.key?('fileName')
74
+ @parent_ostruct = OpenStruct.new
75
+ @parent_ostruct.fileName = locator['fileName']
76
+ @parent_ostruct.driveType = dInfo.driveType
77
+ @parent_ostruct.hyperv_connection = @hyperv_connection unless @hyperv_connection.nil?
78
+ @parent = MiqDisk.getDisk(@parent_ostruct)
79
+ end
80
+ end
81
+
82
+ def getParentPathWin(locator)
83
+ buf = getPathData(locator)
84
+ locator['fileName'] = buf.UnicodeToUtf8!
85
+ end
86
+
87
+ def getPathData(locator)
88
+ @ms_disk_file.seek(MSCommon.getHiLo(locator, "data_offset"), IO::SEEK_SET)
89
+ @ms_disk_file.read(locator['data_length'])
90
+ end
91
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: US-ASCII
2
+
3
+ require 'Scvmm/miq_hyperv_disk'
4
+ require 'disk/modules/MiqLargeFile'
5
+ require 'disk/modules/MSCommon'
6
+
7
+ module MSVSDiskProbe
8
+ MS_MAGIC = "conectix"
9
+
10
+ TYPE_FIXED = 2
11
+ TYPE_DYNAMIC = 3
12
+ TYPE_DIFF = 4
13
+
14
+ MOD_FIXED = "MSVSFixedDisk"
15
+ MOD_DYNAMIC = "MSVSDynamicDisk"
16
+ MOD_DIFF = "MSVSDiffDisk"
17
+
18
+ def self.probe(ostruct)
19
+ return nil unless ostruct.fileName
20
+ # If file not VHD then not Microsoft.
21
+ # Allow ".miq" also.
22
+ ext = File.extname(ostruct.fileName).downcase
23
+ return nil if ext != ".vhd" && ext != ".avhd" && ext != ".miq"
24
+
25
+ if ostruct.hyperv_connection
26
+ ms_disk_file = connect_to_hyperv(ostruct)
27
+ else
28
+ # Get (assumed) footer.
29
+ ms_disk_file = MiqLargeFile.open(ostruct.fileName, "rb")
30
+ end
31
+ footer = MSCommon.getFooter(ms_disk_file, true)
32
+ ms_disk_file.close
33
+
34
+ # Check for MS disk.
35
+ return nil if footer['cookie'] != MS_MAGIC
36
+
37
+ # Return module name to handle type.
38
+ case footer['disk_type']
39
+ when TYPE_FIXED
40
+ return MOD_FIXED
41
+ when TYPE_DYNAMIC
42
+ return MOD_DYNAMIC
43
+ when TYPE_DIFF
44
+ return MOD_DIFF
45
+ else
46
+ raise "Unsupported MS disk: #{footer['disk_type']}"
47
+ end
48
+ end
49
+
50
+ def self.connect_to_hyperv(ostruct)
51
+ connection = ostruct.hyperv_connection
52
+ network = ostruct.driveType == "Network"
53
+ hyperv_disk = MiqHyperVDisk.new(connection[:host],
54
+ connection[:user],
55
+ connection[:password],
56
+ connection[:port],
57
+ network)
58
+ hyperv_disk.open(ostruct.fileName)
59
+ hyperv_disk
60
+ end
61
+ end