manageiq-smartstate 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +4 -0
- data/.rspec_ci +4 -0
- data/.travis.yml +15 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +202 -0
- data/README.md +45 -0
- data/Rakefile +23 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/MiqContainerGroup/MiqContainerGroup.rb +31 -0
- data/lib/MiqVm/MiqLocalVm.rb +50 -0
- data/lib/MiqVm/MiqRhevmVm.rb +179 -0
- data/lib/MiqVm/MiqVm.rb +355 -0
- data/lib/MiqVm/miq_azure_vm.rb +96 -0
- data/lib/MiqVm/miq_scvmm_vm.rb +38 -0
- data/lib/MiqVm/test/camcorder_fleece_test.rb +60 -0
- data/lib/MiqVm/test/localVm.rb +45 -0
- data/lib/MiqVm/test/partitionAlignmentCheck.rb +76 -0
- data/lib/MiqVm/test/remoteVm.rb +65 -0
- data/lib/MiqVm/test/rhevmNfsTest.rb +62 -0
- data/lib/MiqVm/test/rhevmNfsTest2.rb +66 -0
- data/lib/MiqVm/test/rhevmTest.rb +70 -0
- data/lib/OpenStackExtract/MiqOpenStackVm/MiqOpenStackCommon.rb +107 -0
- data/lib/OpenStackExtract/MiqOpenStackVm/MiqOpenStackImage.rb +67 -0
- data/lib/OpenStackExtract/MiqOpenStackVm/MiqOpenStackInstance.rb +182 -0
- data/lib/Scvmm/miq_hyperv_disk.rb +273 -0
- data/lib/Scvmm/miq_scvmm_parse_powershell.rb +75 -0
- data/lib/Scvmm/miq_scvmm_vm_ssa_info.rb +135 -0
- data/lib/Scvmm/test/miq_hyperv_disk_test.rb +33 -0
- data/lib/Scvmm/test/miq_scvmm_vm_ssa_info_test.rb +41 -0
- data/lib/VmLocalDiskAccess/test/localCfg.rb +97 -0
- data/lib/VolumeManager/LVM/logical_volume.rb +75 -0
- data/lib/VolumeManager/LVM/lv_segment.rb +43 -0
- data/lib/VolumeManager/LVM/lvm2disk.rb +158 -0
- data/lib/VolumeManager/LVM/parser.rb +138 -0
- data/lib/VolumeManager/LVM/physical_volume.rb +19 -0
- data/lib/VolumeManager/LVM/scanner.rb +156 -0
- data/lib/VolumeManager/LVM/thin/btree.rb +83 -0
- data/lib/VolumeManager/LVM/thin/constants.rb +86 -0
- data/lib/VolumeManager/LVM/thin/data_map.rb +44 -0
- data/lib/VolumeManager/LVM/thin/mapping_tree.rb +19 -0
- data/lib/VolumeManager/LVM/thin/space_maps.rb +58 -0
- data/lib/VolumeManager/LVM/thin/superblock.rb +136 -0
- data/lib/VolumeManager/LVM/thin.rb +6 -0
- data/lib/VolumeManager/LVM/volume_group.rb +97 -0
- data/lib/VolumeManager/LVM.rb +8 -0
- data/lib/VolumeManager/MiqLdm.rb +546 -0
- data/lib/VolumeManager/MiqLvm.rb +17 -0
- data/lib/VolumeManager/MiqNativeVolumeManager.rb +150 -0
- data/lib/VolumeManager/MiqVolumeManager.rb +277 -0
- data/lib/VolumeManager/VolMgrPlatformSupport.rb +18 -0
- data/lib/VolumeManager/VolMgrPlatformSupportLinux.rb +77 -0
- data/lib/VolumeManager/VolMgrPlatformSupportWin.rb +17 -0
- data/lib/VolumeManager/test/blockDevTest.rb +40 -0
- data/lib/VolumeManager/test/ldm.rb +97 -0
- data/lib/blackbox/VmBlackBox.rb +103 -0
- data/lib/blackbox/xmlStorage.rb +180 -0
- data/lib/db/MiqBdb/MiqBdb.rb +309 -0
- data/lib/db/MiqBdb/MiqBdbBtree.rb +219 -0
- data/lib/db/MiqBdb/MiqBdbHash.rb +199 -0
- data/lib/db/MiqBdb/MiqBdbPage.rb +159 -0
- data/lib/db/MiqBdb/MiqBdbUtil.rb +18 -0
- data/lib/db/MiqSqlite/MiqSqlite3.rb +330 -0
- data/lib/db/MiqSqlite/MiqSqlite3Cell.rb +167 -0
- data/lib/db/MiqSqlite/MiqSqlite3Page.rb +151 -0
- data/lib/db/MiqSqlite/MiqSqlite3Table.rb +124 -0
- data/lib/db/MiqSqlite/MiqSqlite3Util.rb +32 -0
- data/lib/disk/DiskProbe.rb +68 -0
- data/lib/disk/MiqDisk.rb +317 -0
- data/lib/disk/camcorder_test.rb +90 -0
- data/lib/disk/dos_mbr.img +0 -0
- data/lib/disk/modules/AzureBlobDisk.rb +101 -0
- data/lib/disk/modules/LocalDevMod.rb +47 -0
- data/lib/disk/modules/LocalDevProbe.rb +6 -0
- data/lib/disk/modules/MSCommon.rb +352 -0
- data/lib/disk/modules/MSVSDiffDisk.rb +91 -0
- data/lib/disk/modules/MSVSDiskProbe.rb +61 -0
- data/lib/disk/modules/MSVSDynamicDisk.rb +42 -0
- data/lib/disk/modules/MSVSFixedDisk.rb +45 -0
- data/lib/disk/modules/MiqLargeFile.rb +63 -0
- data/lib/disk/modules/MiqLargeFileWin32.rb +107 -0
- data/lib/disk/modules/QcowDisk.rb +692 -0
- data/lib/disk/modules/QcowDiskProbe.rb +34 -0
- data/lib/disk/modules/RawBlockIO.rb +116 -0
- data/lib/disk/modules/RawDisk.rb +45 -0
- data/lib/disk/modules/RawDiskProbe.rb +7 -0
- data/lib/disk/modules/RhevmDescriptor.rb +167 -0
- data/lib/disk/modules/RhevmDiskProbe.rb +52 -0
- data/lib/disk/modules/VMWareCowdDisk.rb +207 -0
- data/lib/disk/modules/VMWareDescriptor.rb +214 -0
- data/lib/disk/modules/VMWareDiskProbe.rb +74 -0
- data/lib/disk/modules/VMWareSparseDisk.rb +189 -0
- data/lib/disk/modules/VhdxDisk.rb +625 -0
- data/lib/disk/modules/VhdxDiskProbe.rb +46 -0
- data/lib/disk/modules/VixDiskMod.rb +54 -0
- data/lib/disk/modules/VixDiskProbe.rb +6 -0
- data/lib/disk/modules/miq_disk_cache.rb +135 -0
- data/lib/disk/modules/miq_dummy_disk.rb +41 -0
- data/lib/disk/modules/vhdx_bat_entry.rb +10 -0
- data/lib/disk/test.rb +66 -0
- data/lib/fs/MetakitFS/MetakitFS.rb +530 -0
- data/lib/fs/MetakitFS/test/Makefile +14 -0
- data/lib/fs/MetakitFS/test/MkCollectFiles.rb +165 -0
- data/lib/fs/MetakitFS/test/MkSelectFiles.rb +30 -0
- data/lib/fs/MetakitFS/test/collect_files.yaml +70 -0
- data/lib/fs/MetakitFS/test/init.rb +3 -0
- data/lib/fs/MetakitFS/test/mk2vmdk.rb +64 -0
- data/lib/fs/MetakitFS/test/mk4test.c +92 -0
- data/lib/fs/MetakitFS/test/mkFsTest.rb +113 -0
- data/lib/fs/MetakitFS/test/proto.rb +97 -0
- data/lib/fs/MiqFS/FsProbe.rb +39 -0
- data/lib/fs/MiqFS/MiqFS.rb +515 -0
- data/lib/fs/MiqFS/modules/AUFSProbe.rb +26 -0
- data/lib/fs/MiqFS/modules/Ext3.rb +305 -0
- data/lib/fs/MiqFS/modules/Ext3Probe.rb +25 -0
- data/lib/fs/MiqFS/modules/Ext4.rb +304 -0
- data/lib/fs/MiqFS/modules/Ext4Probe.rb +25 -0
- data/lib/fs/MiqFS/modules/Fat32.rb +318 -0
- data/lib/fs/MiqFS/modules/Fat32Probe.rb +30 -0
- data/lib/fs/MiqFS/modules/HFSProbe.rb +18 -0
- data/lib/fs/MiqFS/modules/Iso9660.rb +293 -0
- data/lib/fs/MiqFS/modules/Iso9660Probe.rb +18 -0
- data/lib/fs/MiqFS/modules/LocalFS.rb +105 -0
- data/lib/fs/MiqFS/modules/NTFS.rb +287 -0
- data/lib/fs/MiqFS/modules/NTFSProbe.rb +21 -0
- data/lib/fs/MiqFS/modules/NativeFS.rb +155 -0
- data/lib/fs/MiqFS/modules/ReFSProbe.rb +17 -0
- data/lib/fs/MiqFS/modules/RealFS.rb +79 -0
- data/lib/fs/MiqFS/modules/RealFSProbe.rb +6 -0
- data/lib/fs/MiqFS/modules/Reiser4Probe.rb +18 -0
- data/lib/fs/MiqFS/modules/ReiserFS.rb +315 -0
- data/lib/fs/MiqFS/modules/ReiserFSProbe.rb +42 -0
- data/lib/fs/MiqFS/modules/UnionFSProbe.rb +18 -0
- data/lib/fs/MiqFS/modules/WebDAV.rb +127 -0
- data/lib/fs/MiqFS/modules/WebDAVFile.rb +68 -0
- data/lib/fs/MiqFS/modules/XFS.rb +300 -0
- data/lib/fs/MiqFS/modules/XFSProbe.rb +26 -0
- data/lib/fs/MiqFS/modules/ZFSProbe.rb +18 -0
- data/lib/fs/MiqFS/test.rb +59 -0
- data/lib/fs/MiqFsUtil.rb +383 -0
- data/lib/fs/MiqMountManager.rb +209 -0
- data/lib/fs/MiqNativeMountManager.rb +101 -0
- data/lib/fs/MountManagerProbe.rb +29 -0
- data/lib/fs/ReiserFS/block.rb +209 -0
- data/lib/fs/ReiserFS/directory.rb +136 -0
- data/lib/fs/ReiserFS/directory_entry.rb +140 -0
- data/lib/fs/ReiserFS/file_data.rb +111 -0
- data/lib/fs/ReiserFS/superblock.rb +140 -0
- data/lib/fs/ReiserFS/utils.rb +95 -0
- data/lib/fs/VimDatastoreFS/VimDatastoreFS.rb +192 -0
- data/lib/fs/ext3/alloc_bitmap.rb +38 -0
- data/lib/fs/ext3/block_pointers_path.rb +130 -0
- data/lib/fs/ext3/directory.rb +51 -0
- data/lib/fs/ext3/directory_entry.rb +67 -0
- data/lib/fs/ext3/ex_attrib_header.rb +14 -0
- data/lib/fs/ext3/ex_attrib_name.rb +23 -0
- data/lib/fs/ext3/file_data.rb +130 -0
- data/lib/fs/ext3/group_descriptor_entry.rb +65 -0
- data/lib/fs/ext3/group_descriptor_table.rb +54 -0
- data/lib/fs/ext3/hash_tree_entry.rb +18 -0
- data/lib/fs/ext3/hash_tree_header.rb +15 -0
- data/lib/fs/ext3/inode.rb +228 -0
- data/lib/fs/ext3/posix_acl_entry.rb +29 -0
- data/lib/fs/ext3/posix_acl_header.rb +11 -0
- data/lib/fs/ext3/superblock.rb +406 -0
- data/lib/fs/ext3/test/tc_Ext3BlockPointersPath.rb +74 -0
- data/lib/fs/ext4/alloc_bitmap.rb +38 -0
- data/lib/fs/ext4/directory.rb +87 -0
- data/lib/fs/ext4/directory_entry.rb +77 -0
- data/lib/fs/ext4/ex_attrib_header.rb +14 -0
- data/lib/fs/ext4/ex_attrib_name.rb +23 -0
- data/lib/fs/ext4/extent.rb +35 -0
- data/lib/fs/ext4/extent_header.rb +40 -0
- data/lib/fs/ext4/extent_index.rb +33 -0
- data/lib/fs/ext4/group_descriptor_entry.rb +69 -0
- data/lib/fs/ext4/group_descriptor_table.rb +54 -0
- data/lib/fs/ext4/hash_tree_entry.rb +58 -0
- data/lib/fs/ext4/hash_tree_header.rb +35 -0
- data/lib/fs/ext4/inode.rb +465 -0
- data/lib/fs/ext4/posix_acl_entry.rb +29 -0
- data/lib/fs/ext4/posix_acl_header.rb +11 -0
- data/lib/fs/ext4/superblock.rb +412 -0
- data/lib/fs/fat32/boot_sect.rb +379 -0
- data/lib/fs/fat32/directory.rb +222 -0
- data/lib/fs/fat32/directory_entry.rb +540 -0
- data/lib/fs/fat32/file_data.rb +128 -0
- data/lib/fs/iso9660/boot_sector.rb +170 -0
- data/lib/fs/iso9660/directory.rb +90 -0
- data/lib/fs/iso9660/directory_entry.rb +147 -0
- data/lib/fs/iso9660/file_data.rb +78 -0
- data/lib/fs/iso9660/rock_ridge.rb +329 -0
- data/lib/fs/iso9660/util.rb +57 -0
- data/lib/fs/modules/LinuxMount.rb +300 -0
- data/lib/fs/modules/LinuxMountProbe.rb +29 -0
- data/lib/fs/modules/WinMount.rb +97 -0
- data/lib/fs/modules/WinMountProbe.rb +24 -0
- data/lib/fs/ntfs/attrib_attribute_list.rb +131 -0
- data/lib/fs/ntfs/attrib_bitmap.rb +26 -0
- data/lib/fs/ntfs/attrib_data.rb +74 -0
- data/lib/fs/ntfs/attrib_file_name.rb +110 -0
- data/lib/fs/ntfs/attrib_header.rb +194 -0
- data/lib/fs/ntfs/attrib_index_allocation.rb +19 -0
- data/lib/fs/ntfs/attrib_index_root.rb +247 -0
- data/lib/fs/ntfs/attrib_object_id.rb +40 -0
- data/lib/fs/ntfs/attrib_standard_information.rb +107 -0
- data/lib/fs/ntfs/attrib_type.rb +49 -0
- data/lib/fs/ntfs/attrib_volume_information.rb +53 -0
- data/lib/fs/ntfs/attrib_volume_name.rb +31 -0
- data/lib/fs/ntfs/boot_sect.rb +253 -0
- data/lib/fs/ntfs/data_run.rb +358 -0
- data/lib/fs/ntfs/directory_index_node.rb +114 -0
- data/lib/fs/ntfs/index_node_header.rb +69 -0
- data/lib/fs/ntfs/index_record_header.rb +85 -0
- data/lib/fs/ntfs/mft_entry.rb +288 -0
- data/lib/fs/ntfs/utils.rb +43 -0
- data/lib/fs/test/camcorder_fs_test.rb +108 -0
- data/lib/fs/test/collect_files_direct.yaml +22 -0
- data/lib/fs/test/collect_files_in.yaml +24 -0
- data/lib/fs/test/collect_files_in_nc.yaml +22 -0
- data/lib/fs/test/collect_files_out.yaml +6 -0
- data/lib/fs/test/collect_files_rm.yaml +6 -0
- data/lib/fs/test/copyTest.rb +126 -0
- data/lib/fs/test/fsTest.rb +87 -0
- data/lib/fs/test/updateTest.rb +184 -0
- data/lib/fs/xfs/allocation_group.rb +160 -0
- data/lib/fs/xfs/bmap_btree_block.rb +125 -0
- data/lib/fs/xfs/bmap_btree_record.rb +80 -0
- data/lib/fs/xfs/bmap_btree_root_node.rb +72 -0
- data/lib/fs/xfs/directory.rb +133 -0
- data/lib/fs/xfs/directory2_data_header.rb +27 -0
- data/lib/fs/xfs/directory3_data_header.rb +34 -0
- data/lib/fs/xfs/directory_block_tail.rb +22 -0
- data/lib/fs/xfs/directory_data_header.rb +46 -0
- data/lib/fs/xfs/directory_entry.rb +106 -0
- data/lib/fs/xfs/inode.rb +532 -0
- data/lib/fs/xfs/inode_map.rb +100 -0
- data/lib/fs/xfs/short_form_directory_entry.rb +91 -0
- data/lib/fs/xfs/short_form_header.rb +44 -0
- data/lib/fs/xfs/superblock.rb +556 -0
- data/lib/lib/tasks/azure.rake +52 -0
- data/lib/manageiq/smartstate/version.rb +5 -0
- data/lib/manageiq/smartstate.rb +7 -0
- data/lib/manageiq-smartstate.rb +1 -0
- data/lib/metadata/MIQExtract/MIQExtract.rb +297 -0
- data/lib/metadata/MIQExtract/test/extractTest.rb +41 -0
- data/lib/metadata/MIQExtract/test/full_extract_test.rb +68 -0
- data/lib/metadata/ScanProfile/HostScanItem.rb +4 -0
- data/lib/metadata/ScanProfile/HostScanProfile.rb +4 -0
- data/lib/metadata/ScanProfile/HostScanProfiles.rb +41 -0
- data/lib/metadata/ScanProfile/ScanItemBase.rb +63 -0
- data/lib/metadata/ScanProfile/ScanProfileBase.rb +51 -0
- data/lib/metadata/ScanProfile/ScanProfilesBase.rb +60 -0
- data/lib/metadata/ScanProfile/VmScanItem.rb +4 -0
- data/lib/metadata/ScanProfile/VmScanProfile.rb +4 -0
- data/lib/metadata/ScanProfile/VmScanProfiles.rb +38 -0
- data/lib/metadata/ScanProfile/modules/HostScanItemFile.rb +51 -0
- data/lib/metadata/ScanProfile/modules/HostScanItemNteventlog.rb +84 -0
- data/lib/metadata/ScanProfile/modules/VmScanItemFile.rb +39 -0
- data/lib/metadata/ScanProfile/modules/VmScanItemNteventlog.rb +34 -0
- data/lib/metadata/ScanProfile/modules/VmScanItemRegistry.rb +64 -0
- data/lib/metadata/VMMount/VMMount.rb +81 -0
- data/lib/metadata/VMMount/VMPlatformMount.rb +18 -0
- data/lib/metadata/VMMount/VMPlatformMountLinux.rb +75 -0
- data/lib/metadata/VMMount/VMPlatformMountWin.rb +13 -0
- data/lib/metadata/VmConfig/GetNativeCfg.rb +45 -0
- data/lib/metadata/VmConfig/VmConfig.rb +947 -0
- data/lib/metadata/VmConfig/cfgConfig.rb +45 -0
- data/lib/metadata/VmConfig/ovfConfig.rb +99 -0
- data/lib/metadata/VmConfig/test/GetVMwareCfgTest.rb +40 -0
- data/lib/metadata/VmConfig/vmcConfig.rb +116 -0
- data/lib/metadata/VmConfig/vmtxConfig.rb +4 -0
- data/lib/metadata/VmConfig/vmxConfig.rb +162 -0
- data/lib/metadata/VmConfig/xmlConfig.rb +79 -0
- data/lib/metadata/VmConfig/xmlMsHyperVConfig.rb +41 -0
- data/lib/metadata/linux/InitProcHash.rb +632 -0
- data/lib/metadata/linux/LinuxInitProcs.rb +142 -0
- data/lib/metadata/linux/LinuxOSInfo.rb +237 -0
- data/lib/metadata/linux/LinuxPackages.rb +209 -0
- data/lib/metadata/linux/LinuxSystemd.rb +130 -0
- data/lib/metadata/linux/LinuxUsers.rb +289 -0
- data/lib/metadata/linux/LinuxUtils.rb +197 -0
- data/lib/metadata/linux/MiqConaryPackages.rb +41 -0
- data/lib/metadata/linux/MiqRpmPackages.rb +160 -0
- data/lib/metadata/linux/test/Name +0 -0
- data/lib/metadata/linux/test/Packages +0 -0
- data/lib/metadata/linux/test/rpoTest.rb +5 -0
- data/lib/metadata/linux/test/tc_LinuxUtils.rb +4157 -0
- data/lib/metadata/util/event_log_filter.rb +61 -0
- data/lib/metadata/util/md5deep.rb +280 -0
- data/lib/metadata/util/win32/Win32Accounts.rb +764 -0
- data/lib/metadata/util/win32/Win32EventLog.rb +743 -0
- data/lib/metadata/util/win32/Win32Services.rb +86 -0
- data/lib/metadata/util/win32/Win32Software.rb +326 -0
- data/lib/metadata/util/win32/Win32System.rb +333 -0
- data/lib/metadata/util/win32/boot_info_win.rb +59 -0
- data/lib/metadata/util/win32/fleece_hives.rb +220 -0
- data/lib/metadata/util/win32/ms-registry.rb +650 -0
- data/lib/metadata/util/win32/peheader.rb +868 -0
- data/lib/metadata/util/win32/remote-registry.rb +142 -0
- data/lib/metadata/util/win32/system_path_win.rb +103 -0
- data/lib/metadata/util/win32/versioninfo.rb +17 -0
- data/manageiq-smartstate.gemspec +35 -0
- 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,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
|