manageiq-smartstate 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yaml +31 -0
- data/.rspec +0 -1
- data/.whitesource +3 -0
- data/Gemfile +1 -1
- data/README.md +1 -2
- data/lib/MiqVm/MiqRhevmVm.rb +1 -0
- data/lib/MiqVm/MiqVm.rb +0 -7
- data/lib/blackbox/VmBlackBox.rb +1 -0
- data/lib/db/MiqBdb/MiqBdb.rb +1 -0
- data/lib/db/MiqBdb/MiqBdbBtree.rb +1 -0
- data/lib/db/MiqBdb/MiqBdbHash.rb +1 -0
- data/lib/db/MiqBdb/MiqBdbPage.rb +1 -0
- data/lib/disk/DiskProbe.rb +2 -1
- data/lib/disk/modules/MiqLargeFile.rb +1 -0
- data/lib/fs/ntfs/attrib_file_name.rb +1 -0
- data/lib/fs/ntfs/attrib_standard_information.rb +1 -0
- data/lib/manageiq/smartstate/version.rb +1 -1
- data/lib/metadata/MIQExtract/MIQExtract.rb +1 -0
- data/lib/metadata/ScanProfile/ScanProfilesBase.rb +1 -0
- data/lib/metadata/VmConfig/GetNativeCfg.rb +1 -0
- data/lib/metadata/VmConfig/VmConfig.rb +1 -0
- data/lib/metadata/VmConfig/ovfConfig.rb +1 -0
- data/lib/metadata/VmConfig/vmcConfig.rb +1 -0
- data/lib/metadata/VmConfig/xmlConfig.rb +1 -6
- data/lib/metadata/linux/LinuxInitProcs.rb +1 -0
- data/lib/metadata/linux/LinuxOSInfo.rb +1 -0
- data/lib/metadata/linux/LinuxPackages.rb +1 -0
- data/lib/metadata/linux/LinuxSystemd.rb +1 -0
- data/lib/metadata/linux/LinuxUsers.rb +1 -0
- data/lib/metadata/linux/MiqConaryPackages.rb +1 -0
- data/lib/metadata/linux/MiqRpmPackages.rb +1 -0
- data/lib/metadata/util/md5deep.rb +1 -0
- data/lib/metadata/util/win32/Win32Accounts.rb +1 -0
- data/lib/metadata/util/win32/Win32EventLog.rb +1 -0
- data/lib/metadata/util/win32/Win32Services.rb +1 -0
- data/lib/metadata/util/win32/Win32Software.rb +1 -0
- data/lib/metadata/util/win32/Win32System.rb +1 -0
- data/lib/metadata/util/win32/fleece_hives.rb +1 -0
- data/lib/metadata/util/win32/ms-registry.rb +1 -0
- data/lib/metadata/util/win32/remote-registry.rb +1 -0
- data/manageiq-smartstate.gemspec +4 -5
- metadata +7 -32
- data/.travis.yml +0 -15
- data/lib/MiqVm/miq_scvmm_vm.rb +0 -39
- data/lib/Scvmm/miq_hyperv_disk.rb +0 -274
- data/lib/Scvmm/miq_scvmm_parse_powershell.rb +0 -75
- data/lib/Scvmm/miq_scvmm_vm_ssa_info.rb +0 -135
- data/lib/disk/modules/MSCommon.rb +0 -354
- data/lib/disk/modules/MSVSDiffDisk.rb +0 -85
- data/lib/disk/modules/MSVSDiskProbe.rb +0 -61
- data/lib/disk/modules/MSVSDynamicDisk.rb +0 -36
- data/lib/disk/modules/MSVSFixedDisk.rb +0 -39
- data/lib/disk/modules/VhdxDisk.rb +0 -629
- data/lib/disk/modules/VhdxDiskProbe.rb +0 -46
- data/lib/metadata/VmConfig/xmlMsHyperVConfig.rb +0 -41
@@ -1,354 +0,0 @@
|
|
1
|
-
require 'disk/modules/MiqLargeFile'
|
2
|
-
require 'miq_unicode'
|
3
|
-
require 'binary_struct'
|
4
|
-
require 'memory_buffer'
|
5
|
-
require 'Scvmm/miq_hyperv_disk'
|
6
|
-
|
7
|
-
module MSCommon
|
8
|
-
using ManageIQ::UnicodeString
|
9
|
-
|
10
|
-
# NOTE: All values are stored in network byte order.
|
11
|
-
|
12
|
-
FOOTER = BinaryStruct.new([
|
13
|
-
'a8', 'cookie', # Always 'conectix'.
|
14
|
-
'N', 'features', # Should be 2 or 3 (bit 0 is temp disk).
|
15
|
-
'N', 'version', # Major/Minor file format version.
|
16
|
-
'N', 'data_offset_hi', # Offset from beginning of file to next data struct (dyn & diff only, 0xffffffff for fixed).
|
17
|
-
'N', 'data_offset_lo',
|
18
|
-
'N', 'time_stamp', # Create time (sec since Jan 1 2000 12:00 AM in GMT).
|
19
|
-
'a4', 'creator_app', # Virtual PC = 'vpc ', Virtual Server = 'vs '.
|
20
|
-
'N', 'creator_ver', # Major/Minor ver of creator app.
|
21
|
-
'N', 'creator_host', # Creator host: Windows = 0x5769326b ('Wi2k'); Macintosh = 0x4d616320 ('Mac ').
|
22
|
-
'N', 'original_size_hi', # Original size of disk.
|
23
|
-
'N', 'original_size_lo',
|
24
|
-
'N', 'current_size_hi', # Current size of the disk.
|
25
|
-
'N', 'current_size_lo',
|
26
|
-
'N', 'disk_geometry', # CHS (byte sizes 2, 1, 1) values for disk.
|
27
|
-
'N', 'disk_type', # Disk subtype (Fixed, Dynamic or Differencing).
|
28
|
-
'N', 'checksum', # One's compliment of sum of struct minus this field.
|
29
|
-
'a16', 'unique_id', # UUID.
|
30
|
-
'C', 'saved_state', # If 1, system is in 'saved state'.
|
31
|
-
])
|
32
|
-
|
33
|
-
HEADER = BinaryStruct.new([
|
34
|
-
'a8', 'cookie', # Always 'cxsparse'.
|
35
|
-
'Q', 'data_offset', # Unused, should be 0xffffffff.
|
36
|
-
'N', 'table_offset_hi', # Byte offset to the Block Allocation Table.
|
37
|
-
'N', 'table_offset_lo',
|
38
|
-
'N', 'header_ver', # Major/Minor header version.
|
39
|
-
'N', 'max_tbl_ent', # Max entries in the BAT.
|
40
|
-
'N', 'block_size', # Size of data section of a block, default 2M (0x00200000).
|
41
|
-
'N', 'checksum', # One's compliment sum of all fields minus this one.
|
42
|
-
'a16', 'parent_uuid', # Parent disk UUID (for differencing disk only).
|
43
|
-
'N', 'parent_tstamp', # MTime of parent disk (sec since Jan 1 2000 12:00 AM in GMT).
|
44
|
-
'N', 'reserved1', # reserved, should be 0.
|
45
|
-
'a512', 'parent_uname', # Parent disk filename in UNICODE (UTF-16).
|
46
|
-
'a24', 'parent_loc1', # Parent locator entries.
|
47
|
-
'a24', 'parent_loc2',
|
48
|
-
'a24', 'parent_loc3',
|
49
|
-
'a24', 'parent_loc4',
|
50
|
-
'a24', 'parent_loc5',
|
51
|
-
'a24', 'parent_loc6',
|
52
|
-
'a24', 'parent_loc7',
|
53
|
-
'a24', 'parent_loc8',
|
54
|
-
])
|
55
|
-
|
56
|
-
PARENT_LOCATOR = BinaryStruct.new([
|
57
|
-
'a4', 'platform_code', # Platform specific format used for locator.
|
58
|
-
'N', 'data_space', # Number of sectors used to store locator.
|
59
|
-
'N', 'data_length', # Byte length of locator.
|
60
|
-
'N', 'reserved1', # Must be zero.
|
61
|
-
'N', 'data_offset_hi', # Absolute byte offset of locator.
|
62
|
-
'N', 'data_offset_lo',
|
63
|
-
])
|
64
|
-
|
65
|
-
BAE_SIZE = 4
|
66
|
-
SECTOR_LENGTH = 512
|
67
|
-
FOOTER_LENGTH = 512
|
68
|
-
HEADER_LOCATION = 512
|
69
|
-
BLOCK_NOT_ALLOCATED = 0xffffffff
|
70
|
-
SUPPORTED_HEADER_VERSION = 0x00010000
|
71
|
-
|
72
|
-
def self.connect_to_hyperv(ostruct)
|
73
|
-
connection = ostruct.hyperv_connection
|
74
|
-
@network = ostruct.driveType == "Network"
|
75
|
-
hyperv_disk = MiqHyperVDisk.new(connection[:host],
|
76
|
-
connection[:user],
|
77
|
-
connection[:password],
|
78
|
-
connection[:port],
|
79
|
-
@network)
|
80
|
-
hyperv_disk.open(ostruct.fileName)
|
81
|
-
hyperv_disk
|
82
|
-
end
|
83
|
-
|
84
|
-
def self.d_init_common(dInfo, file)
|
85
|
-
@dInfo = dInfo
|
86
|
-
@blockSize = SECTOR_LENGTH
|
87
|
-
@file = file
|
88
|
-
|
89
|
-
# Get file, footer & header, do footer verification.
|
90
|
-
@footer = getFooter(@file, true)
|
91
|
-
@header = getHeader(@footer, true)
|
92
|
-
verifyFooterCopy(@footer)
|
93
|
-
|
94
|
-
# Verify footer copy.
|
95
|
-
|
96
|
-
# Verify format version number (must be 0x00010000).
|
97
|
-
raise "Incompatible header version: 0x#{'%04x' % @header['header_ver']}" if @header['header_ver'] != SUPPORTED_HEADER_VERSION
|
98
|
-
|
99
|
-
# Calc sectors per block, bytes in block sector bitmap & BAT loc.
|
100
|
-
@secPerBlock = @header['block_size'] / @blockSize
|
101
|
-
@blockSectorBitmapByteCount = @secPerBlock / 8
|
102
|
-
if (bd = @blockSectorBitmapByteCount % 512) != 0
|
103
|
-
@blockSectorBitmapByteCount = @blockSectorBitmapByteCount + 512 - bd
|
104
|
-
end
|
105
|
-
@batBase = getHiLo(@header, "table_offset")
|
106
|
-
process_bae
|
107
|
-
end
|
108
|
-
|
109
|
-
def self.d_read_common(pos, len, parent = nil)
|
110
|
-
# Get starting & ending block, sector & byte offset of read.
|
111
|
-
blockStart, sectorStart, byteOffsetStart = blockPos(pos)
|
112
|
-
blockEnd, sectorEnd, byteOffsetEnd = blockPos(pos + len - 1)
|
113
|
-
|
114
|
-
# Loop on blocks (2M entities of storage).
|
115
|
-
buf = ""
|
116
|
-
(blockStart..blockEnd).each do |blockNum|
|
117
|
-
# Loop on sectors (512 byte entities of storage).
|
118
|
-
secStart = (blockNum == blockStart) ? sectorStart : 0
|
119
|
-
secEnd = (blockNum == blockEnd) ? sectorEnd : @secPerBlock - 1
|
120
|
-
(secStart..secEnd).each do |secNum|
|
121
|
-
# If STARTING, need to skip to where data is
|
122
|
-
if (blockStart == blockEnd) && (sectorStart == sectorEnd)
|
123
|
-
byteOffset = byteOffsetStart
|
124
|
-
thisLen = len
|
125
|
-
elsif (blockNum == blockStart) && (secNum == sectorStart)
|
126
|
-
byteOffset = byteOffsetStart
|
127
|
-
thisLen = @blockSize - byteOffset
|
128
|
-
# If ENDING, need to account for short read
|
129
|
-
elsif (blockNum == blockEnd) && (secNum == sectorEnd)
|
130
|
-
byteOffset = 0
|
131
|
-
thisLen = len - buf.length
|
132
|
-
raise "Internal Error: Calculated read more than sector: #{thisLen}" if thisLen > @blockSize
|
133
|
-
# Read ENTIRE Sector in all other cases
|
134
|
-
else
|
135
|
-
byteOffset = 0
|
136
|
-
thisLen = @blockSize
|
137
|
-
end
|
138
|
-
|
139
|
-
# If the allocation status of this sector is 0 return zeros.
|
140
|
-
allocStat = getAllocStatus(blockNum, secNum)
|
141
|
-
if allocStat == false
|
142
|
-
if parent.nil?
|
143
|
-
buf << MemoryBuffer.create(thisLen)
|
144
|
-
else
|
145
|
-
buf << parent.d_read(pos + buf.length, thisLen)
|
146
|
-
end
|
147
|
-
else
|
148
|
-
@file.seek(getAbsSectorLoc(blockNum, secNum) + byteOffset, IO::SEEK_SET)
|
149
|
-
buf << @file.read(thisLen)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
buf
|
154
|
-
end
|
155
|
-
|
156
|
-
def self.d_write_common(pos, buf, len, parent = nil)
|
157
|
-
# Get starting & ending block, sector & byte offset of read.
|
158
|
-
blockStart, sectorStart, byteOffsetStart = blockPos(pos)
|
159
|
-
blockEnd, sectorEnd, byteOffsetEnd = blockPos(pos + len - 1)
|
160
|
-
|
161
|
-
# Loop on blocks (2M entities of storage).
|
162
|
-
bytesWritten = 0
|
163
|
-
(blockStart..blockEnd).each do |blockNum|
|
164
|
-
# Loop on sectors (512 byte entities of storage).
|
165
|
-
secStart = (blockNum == blockStart) ? sectorStart : 0
|
166
|
-
secEnd = (blockNum == blockEnd) ? sectorEnd : @secPerBlock - 1
|
167
|
-
(secStart..secEnd).each do |secNum|
|
168
|
-
# If STARTING, need to skip to where data is
|
169
|
-
if (blockStart == blockEnd) && (sectorStart == sectorEnd)
|
170
|
-
byteOffset = byteOffsetStart
|
171
|
-
thisLen = len
|
172
|
-
elsif (blockNum == blockStart) && (secNum == sectorStart)
|
173
|
-
byteOffset = byteOffsetStart
|
174
|
-
thisLen = @blockSize - byteOffset
|
175
|
-
# If ENDING, need to account for short read
|
176
|
-
elsif (blockNum == blockEnd) && (secNum == sectorEnd)
|
177
|
-
byteOffset = 0
|
178
|
-
thisLen = len - bytesWritten
|
179
|
-
raise "Internal Error: Calculated read more than sector: #{thisLen}" if thisLen > @blockSize
|
180
|
-
# Read ENTIRE Sector in all other cases
|
181
|
-
else
|
182
|
-
byteOffset = 0
|
183
|
-
thisLen = @blockSize
|
184
|
-
end
|
185
|
-
|
186
|
-
# If the allocation status of this sector is 0 then allocate it.
|
187
|
-
allocStat = getAllocStatus(blockNum, secNum)
|
188
|
-
allocSector(blockNum, secNum, pos + bytesWritten, parent) if allocStat == false
|
189
|
-
@file.seek(getAbsSectorLoc(blockNum, secNum) + byteOffset, IO::SEEK_SET)
|
190
|
-
bytesWritten += @file.write(buf[bytesWritten, thisLen], thisLen)
|
191
|
-
end
|
192
|
-
end
|
193
|
-
bytesWritten
|
194
|
-
end
|
195
|
-
|
196
|
-
# Disk size in sectors.
|
197
|
-
def self.d_size_common
|
198
|
-
getHiLo(@footer, "current_size") / @blockSize
|
199
|
-
end
|
200
|
-
|
201
|
-
def self.getHiLo(hash, member)
|
202
|
-
(hash["#{member}_hi"] << 32) + hash["#{member}_lo"]
|
203
|
-
end
|
204
|
-
|
205
|
-
# Needed by diff disk.
|
206
|
-
def self.header
|
207
|
-
@header
|
208
|
-
end
|
209
|
-
|
210
|
-
def self.getFooter(file, skip_check = false)
|
211
|
-
# NOTE: Spec says that if checksum fails use the copy in the header.
|
212
|
-
# If that fails then the disk is corrupt.
|
213
|
-
file.seek(file.size - FOOTER_LENGTH, IO::SEEK_SET)
|
214
|
-
@footerBuf = file.read(FOOTER_LENGTH)
|
215
|
-
footer = FOOTER.decode(@footerBuf)
|
216
|
-
# TODO: Find out why this checksum test is failing. For now don't call getFooter without skip_check set to "true"
|
217
|
-
unless skip_check
|
218
|
-
footerCsum = checksum(@footerBuf, 64)
|
219
|
-
raise "Footer checksum doesn't match: got 0x#{'%04x' % footerCsum}, s/b 0x#{'%04x' % @footer['checksum']}" if footerCsum != footer['checksum']
|
220
|
-
end
|
221
|
-
footer
|
222
|
-
end
|
223
|
-
|
224
|
-
private
|
225
|
-
|
226
|
-
def self.getHeader(footer, skip_check = false)
|
227
|
-
hdrLoc = getHiLo(footer, "data_offset")
|
228
|
-
hdrSiz = HEADER.size
|
229
|
-
puts "VHD Header is mislocated: 0x#{'%04x' % hdrLoc} (s/b 0x0200)" if hdrLoc != HEADER_LOCATION && !skip_check
|
230
|
-
@file.seek(hdrLoc, IO::SEEK_SET)
|
231
|
-
buf = @file.read(hdrSiz)
|
232
|
-
header = HEADER.decode(buf)
|
233
|
-
# TODO: Find out why this checksum test is failing. For now don't call getHeader without skip_check set to "true"
|
234
|
-
unless skip_check
|
235
|
-
headerCsum = checksum(buf, 36)
|
236
|
-
raise "Header checksum doesn't match: got 0x#{'%04x' % headerCsum}, s/b 0x#{'%04x' % @header['checksum']}" if headerCsum != header['checksum']
|
237
|
-
end
|
238
|
-
header
|
239
|
-
end
|
240
|
-
|
241
|
-
def self.verifyFooterCopy(footer)
|
242
|
-
hdrLoc = getHiLo(footer, "data_offset")
|
243
|
-
@file.seek(hdrLoc - FOOTER_LENGTH, IO::SEEK_SET)
|
244
|
-
footer_copy = FOOTER.decode(@file.read(FOOTER_LENGTH))
|
245
|
-
puts "Footer copy does not match header." if footer_copy != @footer
|
246
|
-
end
|
247
|
-
|
248
|
-
def self.blockPos(pos)
|
249
|
-
rawSectorNumber, byteOffset = pos.divmod(@blockSize)
|
250
|
-
blockNumber, secInBlock = rawSectorNumber.divmod(@secPerBlock)
|
251
|
-
return blockNumber, secInBlock, byteOffset
|
252
|
-
end
|
253
|
-
|
254
|
-
def self.process_bae
|
255
|
-
@file.seek(@batBase, IO::SEEK_SET)
|
256
|
-
@bae = []
|
257
|
-
1.step(@header['max_tbl_ent'], 1) do |block_num|
|
258
|
-
@bae << @file.read(BAE_SIZE).unpack('N')[0]
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
def self.getBAE(blockNumber)
|
263
|
-
@bae[blockNumber]
|
264
|
-
end
|
265
|
-
|
266
|
-
def self.putBAE(blockNum, bae)
|
267
|
-
seekBAE(blockNum)
|
268
|
-
@file.write([bae].pack('N'), BAE_SIZE)
|
269
|
-
end
|
270
|
-
|
271
|
-
def self.seekBAE(blockNum)
|
272
|
-
batOffset = blockNum * BAE_SIZE + @batBase
|
273
|
-
@file.seek(batOffset, IO::SEEK_SET)
|
274
|
-
end
|
275
|
-
|
276
|
-
def self.getAllocStatus(blockNum, sectorNum)
|
277
|
-
sectorMask = seekAllocStatus(blockNum, sectorNum)
|
278
|
-
return false if sectorMask == BLOCK_NOT_ALLOCATED
|
279
|
-
sectorBitmap = @file.read(1).unpack('C')[0]
|
280
|
-
sectorBitmap & sectorMask == sectorMask
|
281
|
-
end
|
282
|
-
|
283
|
-
def self.setAllocStatus(blockNum, sectorNum)
|
284
|
-
sectorMask = seekAllocStatus(blockNum, sectorNum)
|
285
|
-
sectorBitmap = @file.read(1).unpack('C')[0]
|
286
|
-
sectorBitmap |= sectorMask
|
287
|
-
@file.seek(-1, IO::SEEK_CUR)
|
288
|
-
@file.write([sectorBitmap].pack('C'), 1)
|
289
|
-
end
|
290
|
-
|
291
|
-
def self.seekAllocStatus(blockNum, sectorNum)
|
292
|
-
sectorByte, bitOffset = sectorNum.divmod(8)
|
293
|
-
bae = getBAE(blockNum)
|
294
|
-
return bae if bae == BLOCK_NOT_ALLOCATED
|
295
|
-
@file.seek(bae * @blockSize + sectorByte, IO::SEEK_SET)
|
296
|
-
0x80 >> bitOffset
|
297
|
-
end
|
298
|
-
|
299
|
-
def self.getAbsSectorLoc(blockNum, sectorNum)
|
300
|
-
getBAE(blockNum) * @blockSize + sectorNum * @blockSize + @blockSectorBitmapByteCount
|
301
|
-
end
|
302
|
-
|
303
|
-
def self.allocSector(blockNum, sectorNum, pos, parent)
|
304
|
-
allocBlock(blockNum) if getBAE(blockNum) == BLOCK_NOT_ALLOCATED
|
305
|
-
if parent.nil?
|
306
|
-
buf = MemoryBuffer.create(@blockSize)
|
307
|
-
else
|
308
|
-
sector = pos.divmod(@blockSize)[0]
|
309
|
-
buf = parent.d_read(sector, @blockSize)
|
310
|
-
end
|
311
|
-
setAllocStatus(blockNum, sectorNum)
|
312
|
-
@file.seek(getAbsSectorLoc(blockNum, sectorNum), IO::SEEK_SET)
|
313
|
-
@file.write(buf, buf.size)
|
314
|
-
end
|
315
|
-
|
316
|
-
def self.allocBlock(blockNum)
|
317
|
-
# Alloc block.
|
318
|
-
pos = @file.size - FOOTER_LENGTH
|
319
|
-
sector = findFreeSector
|
320
|
-
putBAE(blockNum, sector)
|
321
|
-
# Write sector alloc bitmap.
|
322
|
-
bmp = MemoryBuffer.create(@blockSectorBitmapByteCount)
|
323
|
-
@file.seek(sector * @blockSize, IO::SEEK_SET)
|
324
|
-
@file.write(bmp, bmp.size)
|
325
|
-
# Footer has to move. Total size is 2048 + size of data blocks.
|
326
|
-
pos += @secPerBlock * @blockSize
|
327
|
-
@file.seek(pos, IO::SEEK_SET)
|
328
|
-
@file.write(@footerBuf, @footerBuf.size)
|
329
|
-
end
|
330
|
-
|
331
|
-
def self.findFreeSector
|
332
|
-
# Find a free disk sector with which to start a new block.
|
333
|
-
if @freeSector.nil?
|
334
|
-
seekBAE(0); ents = @header['max_tbl_ent']
|
335
|
-
baes = @file.read(ents * BAE_SIZE).unpack("N#{ents}")
|
336
|
-
baes.delete(BLOCK_NOT_ALLOCATED)
|
337
|
-
raise "Disk full." if baes.size == @header['max_tbl_ent']
|
338
|
-
@freeSector = baes.max
|
339
|
-
end
|
340
|
-
@freeSector += @secPerBlock
|
341
|
-
raise "Disk full." if @freeSector > d_size_common / @blockSize
|
342
|
-
@freeSector
|
343
|
-
end
|
344
|
-
|
345
|
-
def self.checksum(buf, skip_offset)
|
346
|
-
csum = 0
|
347
|
-
0.upto(buf.size - 1) do|i|
|
348
|
-
next if i >= skip_offset && i < skip_offset + 4
|
349
|
-
csum += buf[i].to_i
|
350
|
-
end
|
351
|
-
# GRRRRR - convert to actual 32-bits.
|
352
|
-
[~csum].pack('L').unpack('L')[0]
|
353
|
-
end
|
354
|
-
end # module
|
@@ -1,85 +0,0 @@
|
|
1
|
-
# encoding: US-ASCII
|
2
|
-
|
3
|
-
require 'disk/modules/MSCommon'
|
4
|
-
require 'disk/modules/miq_disk_common'
|
5
|
-
|
6
|
-
module MSVSDiffDisk
|
7
|
-
def d_init
|
8
|
-
self.diskType = "MSVS Differencing"
|
9
|
-
self.blockSize = MSCommon::SECTOR_LENGTH
|
10
|
-
fileMode = MiqDiskCommon.file_mode(dInfo)
|
11
|
-
if dInfo.hyperv_connection
|
12
|
-
@hyperv_connection = dInfo.hyperv_connection
|
13
|
-
@ms_disk_file = MSCommon.connect_to_hyperv(dInfo)
|
14
|
-
else
|
15
|
-
@hyperv_connection = nil
|
16
|
-
@ms_disk_file = MiqLargeFile.open(dInfo.fileName, fileMode) unless dInfo.baseOnly
|
17
|
-
end
|
18
|
-
MSCommon.d_init_common(dInfo, @ms_disk_file) unless dInfo.baseOnly
|
19
|
-
|
20
|
-
# Get parent locators.
|
21
|
-
@locators = []
|
22
|
-
1.upto(8) do|idx|
|
23
|
-
@locators << MSCommon::PARENT_LOCATOR.decode(MSCommon.header["parent_loc#{idx}"])
|
24
|
-
next if @locators[idx - 1]['platform_code'] == "\000\000\000\000"
|
25
|
-
locator = @locators[idx - 1]
|
26
|
-
if locator['platform_code'] == "W2ku"
|
27
|
-
getParentPathWin(locator)
|
28
|
-
getParent(locator)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
raise "No compatible parent locator found" if @parent == nil
|
32
|
-
end
|
33
|
-
|
34
|
-
def getBase
|
35
|
-
@parent || self
|
36
|
-
end
|
37
|
-
|
38
|
-
# /////////////////////////////////////////////////////////////////////////
|
39
|
-
# Implementation.
|
40
|
-
|
41
|
-
def d_read(pos, len)
|
42
|
-
MSCommon.d_read_common(pos, len, @parent)
|
43
|
-
end
|
44
|
-
|
45
|
-
def d_write(pos, buf, len)
|
46
|
-
MSCommon.d_write_common(pos, buf, len, @parent)
|
47
|
-
end
|
48
|
-
|
49
|
-
def d_close
|
50
|
-
@parent.close if @parent
|
51
|
-
@ms_disk_file.close
|
52
|
-
end
|
53
|
-
|
54
|
-
def d_size
|
55
|
-
total = 0
|
56
|
-
total = @parent.d_size if @parent
|
57
|
-
total += @ms_disk_file.size
|
58
|
-
total
|
59
|
-
end
|
60
|
-
|
61
|
-
# /////////////////////////////////////////////////////////////////////////
|
62
|
-
# // Helpers.
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def getParent(locator)
|
67
|
-
if locator.key?('fileName')
|
68
|
-
@parent_ostruct = OpenStruct.new
|
69
|
-
@parent_ostruct.fileName = locator['fileName']
|
70
|
-
@parent_ostruct.driveType = dInfo.driveType
|
71
|
-
@parent_ostruct.hyperv_connection = @hyperv_connection unless @hyperv_connection.nil?
|
72
|
-
@parent = MiqDisk.getDisk(@parent_ostruct)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def getParentPathWin(locator)
|
77
|
-
buf = getPathData(locator)
|
78
|
-
locator['fileName'] = buf.UnicodeToUtf8!
|
79
|
-
end
|
80
|
-
|
81
|
-
def getPathData(locator)
|
82
|
-
@ms_disk_file.seek(MSCommon.getHiLo(locator, "data_offset"), IO::SEEK_SET)
|
83
|
-
@ms_disk_file.read(locator['data_length'])
|
84
|
-
end
|
85
|
-
end
|
@@ -1,61 +0,0 @@
|
|
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
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'disk/modules/MSCommon'
|
2
|
-
require 'disk/modules/miq_disk_common'
|
3
|
-
|
4
|
-
module MSVSDynamicDisk
|
5
|
-
def d_init
|
6
|
-
self.diskType = "MSVS Dynamic"
|
7
|
-
self.blockSize = MSCommon::SECTOR_LENGTH
|
8
|
-
fileMode = MiqDiskCommon.file_mode(dInfo)
|
9
|
-
@ms_disk_file = if dInfo.hyperv_connection
|
10
|
-
MSCommon.connect_to_hyperv(dInfo)
|
11
|
-
else
|
12
|
-
MiqLargeFile.open(dInfo.fileName, fileMode)
|
13
|
-
end
|
14
|
-
MSCommon.d_init_common(dInfo, @ms_disk_file)
|
15
|
-
end
|
16
|
-
|
17
|
-
def getBase
|
18
|
-
self
|
19
|
-
end
|
20
|
-
|
21
|
-
def d_read(pos, len)
|
22
|
-
MSCommon.d_read_common(pos, len)
|
23
|
-
end
|
24
|
-
|
25
|
-
def d_write(pos, buf, len)
|
26
|
-
MSCommon.d_write_common(pos, buf, len)
|
27
|
-
end
|
28
|
-
|
29
|
-
def d_close
|
30
|
-
@ms_disk_file.close
|
31
|
-
end
|
32
|
-
|
33
|
-
def d_size
|
34
|
-
MSCommon.d_size_common
|
35
|
-
end
|
36
|
-
end # module
|
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'disk/modules/MiqLargeFile'
|
2
|
-
require 'disk/modules/miq_disk_common'
|
3
|
-
|
4
|
-
module MSVSFixedDisk
|
5
|
-
def d_init
|
6
|
-
@diskType = "MSVSFixed"
|
7
|
-
@blockSize = 512
|
8
|
-
|
9
|
-
fileMode = MiqDiskCommon.file_mode
|
10
|
-
|
11
|
-
if dInfo.hyperv_connection
|
12
|
-
@ms_flat_disk_file = MSCommon.connect_to_hyperv(dInfo)
|
13
|
-
else
|
14
|
-
@ms_flat_disk_file = MiqLargeFile.open(dInfo.fileName, fileMode)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def d_read(pos, len)
|
19
|
-
@ms_flat_disk_file.seek(pos, IO::SEEK_SET)
|
20
|
-
@ms_flat_disk_file.read(len)
|
21
|
-
end
|
22
|
-
|
23
|
-
def getBase
|
24
|
-
self
|
25
|
-
end
|
26
|
-
|
27
|
-
def d_write(pos, buf, len)
|
28
|
-
@ms_flat_disk_file.seek(pos, IO::SEEK_SET)
|
29
|
-
@ms_flat_disk_file.write(buf, len)
|
30
|
-
end
|
31
|
-
|
32
|
-
def d_close
|
33
|
-
@ms_flat_disk_file.close
|
34
|
-
end
|
35
|
-
|
36
|
-
def d_size
|
37
|
-
File.size(dInfo.fileName)
|
38
|
-
end
|
39
|
-
end
|