manageiq-smartstate 0.2.10 → 0.2.11
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/lib/disk/modules/VhdxDisk.rb +1 -0
- data/lib/fs/MiqFS/modules/Ext3.rb +1 -1
- data/lib/fs/MiqFS/modules/ReiserFS.rb +1 -1
- data/lib/fs/MiqFS/modules/XFS.rb +1 -1
- data/lib/fs/ext3/superblock.rb +5 -97
- data/lib/fs/ext4/superblock.rb +5 -104
- data/lib/fs/modules/LinuxMount.rb +144 -110
- data/lib/manageiq/smartstate/version.rb +1 -1
- data/lib/metadata/linux/LinuxSystemd.rb +14 -0
- data/lib/metadata/util/win32/Win32Software.rb +129 -134
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62cf3e30f6bab25afc33edb03fe30b6849f3ae29
|
4
|
+
data.tar.gz: caec40acfd2c105763fa1144faaf3b4d4f7710f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0a520cf41df5a29c3494630d2d35c15deb4d453ca7fef571c4195426f218eff702da0db4e4483444ccccbf712d7f89b5e02de96b6fb5bda816107f491253dd5
|
7
|
+
data.tar.gz: 2c011d60ca5e37f0b80a10cf039eec69940675409101429dec54af3373763247c6297dbd581c6e25d66a37ffd9df917e81554b23f4b473bbb97a99d0e2461bf6
|
@@ -519,6 +519,7 @@ module VhdxDisk
|
|
519
519
|
def parent_disk(path)
|
520
520
|
@parent_ostruct = OpenStruct.new
|
521
521
|
@parent_ostruct.fileName = path
|
522
|
+
@parent_ostruct.scvmm = @scvmm
|
522
523
|
@parent_ostruct.driveType = @scvmm.get_drivetype(path)
|
523
524
|
@parent_ostruct.hyperv_connection = @hyperv_connection if @hyperv_connection
|
524
525
|
parent = MiqDisk.getDisk(@parent_ostruct)
|
data/lib/fs/MiqFS/modules/XFS.rb
CHANGED
data/lib/fs/ext3/superblock.rb
CHANGED
@@ -147,7 +147,7 @@ module Ext3
|
|
147
147
|
|
148
148
|
# /////////////////////////////////////////////////////////////////////////
|
149
149
|
# // initialize
|
150
|
-
attr_reader :numGroups, :fsId, :stream, :numBlocks, :numInodes, :
|
150
|
+
attr_reader :numGroups, :fsId, :stream, :numBlocks, :numInodes, :volName
|
151
151
|
attr_reader :sectorSize, :blockSize
|
152
152
|
|
153
153
|
@@track_inodes = false
|
@@ -169,11 +169,10 @@ module Ext3
|
|
169
169
|
|
170
170
|
# Grab some quick facts & make sure there's nothing wrong. Tight qualification.
|
171
171
|
raise "Ext3::Superblock.initialize: Invalid signature=[#{@sb['signature']}]" if @sb['signature'] != SUPERBLOCK_SIG
|
172
|
-
state
|
173
|
-
|
174
|
-
|
175
|
-
$log.warn("Ext3
|
176
|
-
$log.warn("Ext3 orphan inodes being recovered") if $log && gotBit?(state, FSS_ORPHAN_REC)
|
172
|
+
raise "Ext3::Superblock.initialize: Invalid file system state" if @sb['fs_state'] > FSS_END
|
173
|
+
if @sb['fs_state'] != FSS_CLEAN
|
174
|
+
$log.warn("Ext3 file system has errors") if $log && gotBit?(@sb['fs_state'], FSS_ERR)
|
175
|
+
$log.warn("Ext3 orphan inodes being recovered") if $log && gotBit?(@sb['fs_state'], FSS_ORPHAN_REC)
|
177
176
|
end
|
178
177
|
raise "Ext3::Superblock.initialize: Invalid error handling method=[#{@sb['err_method']}]" if @sb['err_method'] > EHM_PANIC
|
179
178
|
raise "Ext3::Superblock.initialize: Filesystem has extents (ext4)" if gotBit?(@sb['incompat_flags'], ICF_EXTENTS)
|
@@ -198,7 +197,6 @@ module Ext3
|
|
198
197
|
@numGroups += 1 if @lastGroupBlocks > 0
|
199
198
|
@fsId = UUIDTools::UUID.parse_raw(@sb['fs_id'])
|
200
199
|
@volName = @sb['vol_name']
|
201
|
-
@jrnlId = UUIDTools::UUID.parse_raw(@sb['jrnl_id'])
|
202
200
|
end
|
203
201
|
|
204
202
|
# ////////////////////////////////////////////////////////////////////////////
|
@@ -295,8 +293,6 @@ module Ext3
|
|
295
293
|
if block == 0
|
296
294
|
@block_cache[block] = MemoryBuffer.create(@blockSize)
|
297
295
|
else
|
298
|
-
group, offset = blockNumToGroupNum(block)
|
299
|
-
gde = gdt[group]
|
300
296
|
# raise "Block #{block} is not allocated" if (not gde.blockAllocBmp[offset] and not ignore_alloc)
|
301
297
|
|
302
298
|
address = blockToAddress(block) # This function will read the block into our cache
|
@@ -308,99 +304,11 @@ module Ext3
|
|
308
304
|
@block_cache[block]
|
309
305
|
end
|
310
306
|
|
311
|
-
def getFeatureStrings
|
312
|
-
out = "Compatible Feature Flags:\n"
|
313
|
-
cff = @sb['compat_flags']
|
314
|
-
out << " CFF_PREALLOC_DIR_BLKS\n" if gotBit?(cff, CFF_PREALLOC_DIR_BLKS)
|
315
|
-
out << " CFF_AFS_SERVER_INODE\n" if gotBit?(cff, CFF_AFS_SERVER_INODES)
|
316
|
-
out << " CFF_JOURNAL\n" if gotBit?(cff, CFF_JOURNAL)
|
317
|
-
out << " CFF_EXTENDED_ATTRIBS\n" if gotBit?(cff, CFF_EXTENDED_ATTRIBS)
|
318
|
-
out << " CFF_BIG_PART\n" if gotBit?(cff, CFF_BIG_PART)
|
319
|
-
out << " CFF_HASH_INDEX\n" if gotBit?(cff, CFF_HASH_INDEX)
|
320
|
-
extra = cff - (cff & CFF_FLAGS)
|
321
|
-
out << " Extra Flags: 0x%08X\n" % extra if extra != 0
|
322
|
-
out << "Incompatible Feature Flags:\n"
|
323
|
-
icf = @sb['incompat_flags']
|
324
|
-
out << " ICF_COMPRESSION\n" if gotBit?(icf, ICF_COMPRESSION)
|
325
|
-
out << " ICF_FILE_TYPE\n" if gotBit?(icf, ICF_FILE_TYPE)
|
326
|
-
out << " ICF_RECOVER_FS\n" if gotBit?(icf, ICF_RECOVER_FS)
|
327
|
-
out << " ICF_JOURNAL\n" if gotBit?(icf, ICF_JOURNAL)
|
328
|
-
out << " ICF_META_BG\n" if gotBit?(icf, ICF_META_BG)
|
329
|
-
out << " ICF_EXTENTS\n" if gotBit?(icf, ICF_EXTENTS)
|
330
|
-
out << " ICF_64BIT\n" if gotBit?(icf, ICF_64BIT)
|
331
|
-
out << " ICF_MMP\n" if gotBit?(icf, ICF_MMP)
|
332
|
-
out << " ICF_FLEX_BG\n" if gotBit?(icf, ICF_FLEX_BG)
|
333
|
-
out << " ICF_EA_INODE\n" if gotBit?(icf, ICF_EA_INODE)
|
334
|
-
out << " ICF_DIRDATA\n" if gotBit?(icf, ICF_DIRDATA)
|
335
|
-
extra = icf - (icf & ICF_FLAGS)
|
336
|
-
out << " Extra Flags: 0x%08X\n" % extra if extra != 0
|
337
|
-
out << "Read Only Feature Flags:\n"
|
338
|
-
rof = @sb['ro_flags']
|
339
|
-
out << " ROF_SPARSE\n" if gotBit?(rof, ROF_SPARSE)
|
340
|
-
out << " ROF_LARGE_FILES\n" if gotBit?(rof, ROF_LARGE_FILES)
|
341
|
-
out << " ROF_BTREES\n" if gotBit?(rof, ROF_BTREES)
|
342
|
-
extra = rof - (rof & ROF_FLAGS)
|
343
|
-
out << " Extra Flags: 0x%08X\n" % extra if extra != 0
|
344
|
-
out
|
345
|
-
end
|
346
|
-
|
347
307
|
# ////////////////////////////////////////////////////////////////////////////
|
348
308
|
# // Utility functions.
|
349
309
|
|
350
310
|
def gotBit?(field, bit)
|
351
311
|
field & bit == bit
|
352
312
|
end
|
353
|
-
|
354
|
-
# Dump object.
|
355
|
-
def dump
|
356
|
-
out = "\#<#{self.class}:0x#{'%08x' % object_id}>\n"
|
357
|
-
out << "Number of inodes : #{@sb['num_inodes']}\n"
|
358
|
-
out << "Number of blocks : #{@sb['num_blocks']}\n"
|
359
|
-
out << "Reserved blocks : #{@sb['reserved_blocks']}\n"
|
360
|
-
out << "Unallocated blocks : #{@sb['unallocated_blocks']}\n"
|
361
|
-
out << "Unallocated inodes : #{@sb['unallocated_inodes']}\n"
|
362
|
-
out << "Block group 0 : #{@sb['block_group_zero']}\n"
|
363
|
-
out << "Block size : #{@sb['block_size']} (#{@blockSize} bytes)\n"
|
364
|
-
out << "Fragment size : #{@sb['fragment_size']} (#{fragmentSize} bytes)\n"
|
365
|
-
out << "Blocks per group : #{@sb['blocks_in_group']} (#{blocksPerGroup} blocks per group)\n"
|
366
|
-
out << "Fragments per group : #{@sb['fragments_in_group']} (#{fragmentsPerGroup} fragments per group)\n"
|
367
|
-
out << "Inodes per group : #{@sb['inodes_in_group']} (#{inodesPerGroup} inodes per group)\n"
|
368
|
-
out << "Last mount time : #{Time.at(@sb['last_mount_time'])}\n"
|
369
|
-
out << "Last write time : #{Time.at(@sb['last_write_time'])}\n"
|
370
|
-
out << "Current mount count : #{@sb['mount_count']}\n"
|
371
|
-
out << "Maximum mount count : #{@sb['max_mount_count']}\n"
|
372
|
-
out << "Signature : #{@sb['signature']}\n"
|
373
|
-
out << "File system state : #{@sb['fs_state']}\n"
|
374
|
-
out << "Error hndling methd : #{@sb['err_method']}\n"
|
375
|
-
out << "Minor version : #{@sb['ver_minor']}\n"
|
376
|
-
out << "Last consistency check: #{Time.at(@sb['last_check_time'])}\n"
|
377
|
-
out << "Forced check interval : #{@sb['forced_check_int']} sec\n"
|
378
|
-
out << "Creator OS : #{@sb['creator_os']}\n"
|
379
|
-
out << "Major version : #{@sb['ver_major']}\n"
|
380
|
-
out << "UID can use res blocks: #{@sb['uid_res_blocks']}\n"
|
381
|
-
out << "GID can use res blocks: #{@sb['gid_res_blocks']}\n"
|
382
|
-
if isDynamic?
|
383
|
-
out << "First non-res inode : #{@sb['first_inode']}\n"
|
384
|
-
out << "Size of inode : #{@sb['inode_size']}\n"
|
385
|
-
out << "Block group of this SB: #{@sb['block_group']}\n"
|
386
|
-
out << "Compatible features : 0x#{'%08x' % @sb['compat_flags']}\n"
|
387
|
-
out << "Incompatible features : 0x#{'%08x' % @sb['incompat_flags']}\n"
|
388
|
-
out << "Read Only features : 0x#{'%08x' % @sb['ro_flags']}\n"
|
389
|
-
out << "File system id : #{@fsId}\n"
|
390
|
-
out << "Volume name : #{@sb['vol_name']}\n"
|
391
|
-
out << "Last mount path : #{@sb['last_mnt_path']}\n"
|
392
|
-
out << "Algorithm usage bitmap: 0x#{'%08x' % @sb['algo_use_bmp']}\n"
|
393
|
-
out << "Blocks prealloc files : #{@sb['file_prealloc_blks']}\n"
|
394
|
-
out << "Blocks prealloc dirs : #{@sb['dir_prealloc_blks']}\n"
|
395
|
-
out << "Journal id : #{@jrnlId}\n"
|
396
|
-
out << "Journal inode : #{@sb['jrnl_inode']}\n"
|
397
|
-
out << "Journal device : #{@sb['jrnl_device']}\n"
|
398
|
-
out << "Orphan inode head : #{@sb['orphan_head']}\n"
|
399
|
-
end
|
400
|
-
out << "Number of groups : #{numGroups}\n"
|
401
|
-
out << "Free bytes : #{freeBytes}\n"
|
402
|
-
out << getFeatureStrings
|
403
|
-
out
|
404
|
-
end
|
405
313
|
end
|
406
314
|
end # moule Ext3
|
data/lib/fs/ext4/superblock.rb
CHANGED
@@ -142,14 +142,13 @@ module Ext4
|
|
142
142
|
|
143
143
|
# /////////////////////////////////////////////////////////////////////////
|
144
144
|
# // initialize
|
145
|
-
attr_reader :numGroups, :fsId, :stream, :numBlocks, :numInodes, :
|
146
|
-
attr_reader :sectorSize, :blockSize
|
145
|
+
attr_reader :numGroups, :fsId, :stream, :numBlocks, :numInodes, :volName
|
146
|
+
attr_reader :sectorSize, :blockSize
|
147
147
|
|
148
148
|
@@track_inodes = false
|
149
149
|
|
150
150
|
def initialize(stream)
|
151
|
-
raise "Ext4::Superblock.initialize: Nil stream" if stream.nil?
|
152
|
-
@stream = stream
|
151
|
+
raise "Ext4::Superblock.initialize: Nil stream" if (@stream = stream).nil?
|
153
152
|
|
154
153
|
# Seek, read & decode the superblock structure
|
155
154
|
@stream.seek(SUPERBLOCK_OFFSET)
|
@@ -157,9 +156,8 @@ module Ext4
|
|
157
156
|
|
158
157
|
# Grab some quick facts & make sure there's nothing wrong. Tight qualification.
|
159
158
|
raise "Ext4::Superblock.initialize: Invalid signature=[#{@sb['signature']}]" if @sb['signature'] != SUPERBLOCK_SIG
|
160
|
-
state
|
161
|
-
|
162
|
-
if state != FSS_CLEAN
|
159
|
+
raise "Ext4::Superblock.initialize: Invalid file system state" if @sb['fs_state'] > FSS_END
|
160
|
+
if (state = @sb['fs_state']) != FSS_CLEAN
|
163
161
|
$log.warn("Ext4 file system has errors") if $log && gotBit?(state, FSS_ERR)
|
164
162
|
$log.warn("Ext4 orphan inodes being recovered") if $log && gotBit?(state, FSS_ORPHAN_REC)
|
165
163
|
end
|
@@ -185,7 +183,6 @@ module Ext4
|
|
185
183
|
@numGroups += 1 if @lastGroupBlocks > 0
|
186
184
|
@fsId = UUIDTools::UUID.parse_raw(@sb['fs_id'])
|
187
185
|
@volName = @sb['vol_name']
|
188
|
-
@jrnlId = UUIDTools::UUID.parse_raw(@sb['jrnl_id'])
|
189
186
|
end
|
190
187
|
|
191
188
|
# ////////////////////////////////////////////////////////////////////////////
|
@@ -293,8 +290,6 @@ module Ext4
|
|
293
290
|
if block == 0
|
294
291
|
@block_cache[block] = MemoryBuffer.create(@blockSize)
|
295
292
|
else
|
296
|
-
group, offset = blockNumToGroupNum(block)
|
297
|
-
gde = gdt[group]
|
298
293
|
# raise "Block #{block} is not allocated" if (not gde.blockAllocBmp[offset] and not ignore_alloc)
|
299
294
|
|
300
295
|
address = blockToAddress(block) # This function will read the block into our cache
|
@@ -306,49 +301,6 @@ module Ext4
|
|
306
301
|
@block_cache[block]
|
307
302
|
end
|
308
303
|
|
309
|
-
def getFeatureStrings
|
310
|
-
out = "Compatible Feature Flags:\n"
|
311
|
-
cff = @sb['compat_flags']
|
312
|
-
out << " CFF_PREALLOC_DIR_BLKS\n" if gotBit?(cff, CFF_PREALLOC_DIR_BLKS)
|
313
|
-
out << " CFF_AFS_SERVER_INODE\n" if gotBit?(cff, CFF_AFS_SERVER_INODES)
|
314
|
-
out << " CFF_JOURNAL\n" if gotBit?(cff, CFF_JOURNAL)
|
315
|
-
out << " CFF_EXTENDED_ATTRIBS\n" if gotBit?(cff, CFF_EXTENDED_ATTRIBS)
|
316
|
-
out << " CFF_BIG_PART\n" if gotBit?(cff, CFF_BIG_PART)
|
317
|
-
out << " CFF_HASH_INDEX\n" if gotBit?(cff, CFF_HASH_INDEX)
|
318
|
-
extra = cff - (cff & CFF_FLAGS)
|
319
|
-
out << " Extra Flags: 0x%08X\n" % extra if extra != 0
|
320
|
-
|
321
|
-
out << "Incompatible Feature Flags:\n"
|
322
|
-
icf = @sb['incompat_flags']
|
323
|
-
out << " ICF_COMPRESSION\n" if gotBit?(icf, ICF_COMPRESSION)
|
324
|
-
out << " ICF_FILE_TYPE\n" if gotBit?(icf, ICF_FILE_TYPE)
|
325
|
-
out << " ICF_RECOVER_FS\n" if gotBit?(icf, ICF_RECOVER_FS)
|
326
|
-
out << " ICF_JOURNAL\n" if gotBit?(icf, ICF_JOURNAL)
|
327
|
-
out << " ICF_META_BG\n" if gotBit?(icf, ICF_META_BG)
|
328
|
-
out << " ICF_EXTENTS\n" if gotBit?(icf, ICF_EXTENTS)
|
329
|
-
out << " ICF_64BIT\n" if gotBit?(icf, ICF_64BIT)
|
330
|
-
out << " ICF_MMP\n" if gotBit?(icf, ICF_MMP)
|
331
|
-
out << " ICF_FLEX_BG\n" if gotBit?(icf, ICF_FLEX_BG)
|
332
|
-
out << " ICF_EA_INODE\n" if gotBit?(icf, ICF_EA_INODE)
|
333
|
-
out << " ICF_DIRDATA\n" if gotBit?(icf, ICF_DIRDATA)
|
334
|
-
extra = icf - (icf & ICF_FLAGS)
|
335
|
-
out << " Extra Flags: 0x%08X\n" % extra if extra != 0
|
336
|
-
|
337
|
-
out << "Read Only Feature Flags:\n"
|
338
|
-
rof = @sb['ro_flags']
|
339
|
-
out << " ROF_SPARSE\n" if gotBit?(rof, ROF_SPARSE)
|
340
|
-
out << " ROF_LARGE_FILES\n" if gotBit?(rof, ROF_LARGE_FILES)
|
341
|
-
out << " ROF_BTREES\n" if gotBit?(rof, ROF_BTREES)
|
342
|
-
out << " ROF_HUGE_FILE\n" if gotBit?(rof, ROF_HUGE_FILE)
|
343
|
-
out << " ROF_GDT_CSUM\n" if gotBit?(rof, ROF_GDT_CSUM)
|
344
|
-
out << " ROF_DIR_NLINK\n" if gotBit?(rof, ROF_DIR_NLINK)
|
345
|
-
out << " ROF_EXTRA_ISIZE\n" if gotBit?(rof, ROF_EXTRA_ISIZE)
|
346
|
-
extra = rof - (rof & ROF_FLAGS)
|
347
|
-
out << " Extra Flags: 0x%08X\n" % extra if extra != 0
|
348
|
-
|
349
|
-
out
|
350
|
-
end
|
351
|
-
|
352
304
|
# ////////////////////////////////////////////////////////////////////////////
|
353
305
|
# // Utility functions.
|
354
306
|
|
@@ -357,56 +309,5 @@ module Ext4
|
|
357
309
|
end
|
358
310
|
|
359
311
|
# Dump object.
|
360
|
-
def dump
|
361
|
-
out = "\#<#{self.class}:0x#{'%08x' % object_id}>\n"
|
362
|
-
out << "Number of inodes : #{@sb['num_inodes']}\n"
|
363
|
-
out << "Number of blocks : #{@sb['num_blocks']}\n"
|
364
|
-
out << "Reserved blocks : #{@sb['reserved_blocks']}\n"
|
365
|
-
out << "Unallocated blocks : #{@sb['unallocated_blocks']}\n"
|
366
|
-
out << "Unallocated inodes : #{@sb['unallocated_inodes']}\n"
|
367
|
-
out << "Block group 0 : #{@sb['block_group_zero']}\n"
|
368
|
-
out << "Block size : #{@sb['block_size']} (#{@blockSize} bytes)\n"
|
369
|
-
out << "Fragment size : #{@sb['fragment_size']} (#{fragmentSize} bytes)\n"
|
370
|
-
out << "Blocks per group : #{@sb['blocks_in_group']} (#{blocksPerGroup} blocks per group)\n"
|
371
|
-
out << "Fragments per group : #{@sb['fragments_in_group']} (#{fragmentsPerGroup} fragments per group)\n"
|
372
|
-
out << "Inodes per group : #{@sb['inodes_in_group']} (#{inodesPerGroup} inodes per group)\n"
|
373
|
-
out << "Last mount time : #{Time.at(@sb['last_mount_time'])}\n"
|
374
|
-
out << "Last write time : #{Time.at(@sb['last_write_time'])}\n"
|
375
|
-
out << "Current mount count : #{@sb['mount_count']}\n"
|
376
|
-
out << "Maximum mount count : #{@sb['max_mount_count']}\n"
|
377
|
-
out << "Signature : #{@sb['signature']}\n"
|
378
|
-
out << "File system state : #{@sb['fs_state']}\n"
|
379
|
-
out << "Error hndling methd : #{@sb['err_method']}\n"
|
380
|
-
out << "Minor version : #{@sb['ver_minor']}\n"
|
381
|
-
out << "Last consistency check: #{Time.at(@sb['last_check_time'])}\n"
|
382
|
-
out << "Forced check interval : #{@sb['forced_check_int']} sec\n"
|
383
|
-
out << "Creator OS : #{@sb['creator_os']}\n"
|
384
|
-
out << "Major version : #{@sb['ver_major']}\n"
|
385
|
-
out << "UID can use res blocks: #{@sb['uid_res_blocks']}\n"
|
386
|
-
out << "GID can use res blocks: #{@sb['gid_res_blocks']}\n"
|
387
|
-
out << "Group descriptor size : #{@sb['group_desc_size']}\n"
|
388
|
-
if isDynamic?
|
389
|
-
out << "First non-res inode : #{@sb['first_inode']}\n"
|
390
|
-
out << "Size of inode : #{@sb['inode_size']}\n"
|
391
|
-
out << "Block group of this SB: #{@sb['block_group']}\n"
|
392
|
-
out << "Compatible features : 0x#{'%08x' % @sb['compat_flags']}\n"
|
393
|
-
out << "Incompatible features : 0x#{'%08x' % @sb['incompat_flags']}\n"
|
394
|
-
out << "Read Only features : 0x#{'%08x' % @sb['ro_flags']}\n"
|
395
|
-
out << "File system id : #{@fsId}\n"
|
396
|
-
out << "Volume name : #{@sb['vol_name']}\n"
|
397
|
-
out << "Last mount path : #{@sb['last_mnt_path']}\n"
|
398
|
-
out << "Algorithm usage bitmap: 0x#{'%08x' % @sb['algo_use_bmp']}\n"
|
399
|
-
out << "Blocks prealloc files : #{@sb['file_prealloc_blks']}\n"
|
400
|
-
out << "Blocks prealloc dirs : #{@sb['dir_prealloc_blks']}\n"
|
401
|
-
out << "Journal id : #{@jrnlId}\n"
|
402
|
-
out << "Journal inode : #{@sb['jrnl_inode']}\n"
|
403
|
-
out << "Journal device : #{@sb['jrnl_device']}\n"
|
404
|
-
out << "Orphan inode head : #{@sb['orphan_head']}\n"
|
405
|
-
end
|
406
|
-
out << "Number of groups : #{numGroups}\n"
|
407
|
-
out << "Free bytes : #{freeBytes}\n"
|
408
|
-
out << getFeatureStrings
|
409
|
-
out
|
410
|
-
end
|
411
312
|
end
|
412
313
|
end # moule Ext4
|
@@ -9,84 +9,165 @@ module LinuxMount
|
|
9
9
|
@rootFS = MiqFS.getFS(@rootVolume)
|
10
10
|
raise "LinuxMount: could not mount root volume" unless @rootFS
|
11
11
|
|
12
|
+
assign_device_letters
|
13
|
+
fs_spec_hash = build_fstab_spec
|
14
|
+
build_os_names
|
15
|
+
build_mount_point_tree(fs_spec_hash)
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# Given a path to a file, return true if it's a symbolic link.
|
20
|
+
# Otherwise, return false.
|
21
|
+
#
|
22
|
+
def fileSymLink?(p)
|
23
|
+
#
|
24
|
+
# We can't just expand the links in the whole path,
|
25
|
+
# because then, the target file will no longer be a link.
|
26
|
+
# So, we expand the path to the target file, then open
|
27
|
+
# the target file through that path to obtain the link data.
|
28
|
+
#
|
29
|
+
np = normalizePath(p)
|
30
|
+
d = File.dirname(np)
|
31
|
+
f = File.basename(np)
|
32
|
+
|
33
|
+
# Expand the path to the target file.
|
34
|
+
exp_dir = expandLinks(d)
|
35
|
+
|
36
|
+
# Get the file system where the target file resides, and it's local path.
|
37
|
+
fs, lp = getFsPathBase(File.join(exp_dir, f))
|
38
|
+
fs.fileSymLink?(lp)
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Given a path to a symbolic link, return the full
|
43
|
+
# path to where the link points.
|
44
|
+
#
|
45
|
+
def getLinkPath(p)
|
46
|
+
#
|
47
|
+
# We can't just expand the links in the whole path,
|
48
|
+
# because then, the target file will no longer be a link.
|
49
|
+
# So, we expand the path to the target file, then open
|
50
|
+
# the target file through that path to obtain the link data.
|
51
|
+
#
|
52
|
+
np = normalizePath(p)
|
53
|
+
d = File.dirname(np)
|
54
|
+
f = File.basename(np)
|
55
|
+
|
56
|
+
# Expand the path to the target file.
|
57
|
+
exp_dir = expandLinks(d)
|
58
|
+
|
59
|
+
# Get the file system where the target file resides, and it's local path.
|
60
|
+
fs, lp = getFsPathBase(File.join(exp_dir, f))
|
61
|
+
# Read the link data from the file, through its file system.
|
62
|
+
sp = getSymLink(fs, lp)
|
63
|
+
# Construct and return the full path to the link target.
|
64
|
+
return(sp) if sp[0, 1] == '/'
|
65
|
+
normalizePath(File.join(exp_dir, sp))
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def assign_device_letters
|
12
71
|
#
|
13
72
|
# Assign device letters to all ide and scsi devices,
|
14
73
|
# even if they're not visible volumes. We need to do
|
15
74
|
# this to assign the proper device names to visible
|
16
75
|
# devices.
|
17
76
|
#
|
18
|
-
sdLetter
|
19
|
-
ideMap
|
77
|
+
sdLetter = 'a'
|
78
|
+
ideMap = {"ide0:0" => "a", "ide0:1" => "b", "ide1:0" => "c", "ide1:1" => "d"}
|
20
79
|
@devHash = {}
|
21
80
|
@vmConfig.getAllDiskKeys.each do |dk|
|
22
81
|
if dk =~ /^ide.*$/
|
23
82
|
@devHash[dk] = "/dev/hd" + ideMap[dk]
|
24
|
-
$log.debug "LinuxMount: devHash[#{dk}] = /dev/hd#{ideMap[dk]}" if $log.debug?
|
25
83
|
elsif dk =~ /^scsi.*$/
|
26
84
|
@devHash[dk] = "/dev/sd" + sdLetter
|
27
|
-
$log.debug "LinuxMount: devHash[#{dk}] = /dev/sd#{sdLetter}" if $log.debug?
|
28
85
|
sdLetter.succ!
|
29
86
|
end
|
87
|
+
$log.debug("LinuxMount: devHash[#{dk}] = #{devHash[dk]}") if $log.debug
|
30
88
|
end
|
89
|
+
end
|
31
90
|
|
91
|
+
def build_fstab_spec
|
32
92
|
#
|
33
93
|
# Build hash for fstab fs_spec look up.
|
34
94
|
#
|
35
|
-
|
95
|
+
fs_spec_hash = {}
|
36
96
|
@volumes.each do |v|
|
37
|
-
$log.debug
|
97
|
+
$log.debug("LinuxMount: Volume = #{v.dInfo.localDev} (#{v.dInfo.hardwareId}, partition = #{v.partNum})") if $log.debug
|
38
98
|
if v == @rootVolume
|
39
99
|
fs = @rootFS
|
40
|
-
else
|
41
|
-
|
42
|
-
$log.debug "LinuxMount: No filesystem on Volume: #{v.dInfo.localDev}, partition = #{v.partNum}" if $log.debug?
|
43
|
-
next
|
44
|
-
end
|
100
|
+
else
|
101
|
+
(fs = MiqFS.getFS(v)) || next
|
45
102
|
end
|
46
103
|
@allFileSystems << fs
|
47
104
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
unless fs.volName.empty?
|
53
|
-
$log.debug "LinuxMount: adding \"LABEL=#{fs.volName}\" to fsSpecHash" if $log.debug?
|
54
|
-
fsSpecHash["LABEL=#{fs.volName}"] = fs
|
55
|
-
$log.debug "LinuxMount: adding \"LABEL=/#{fs.volName}\" to fsSpecHash" if $log.debug?
|
56
|
-
fsSpecHash["LABEL=/#{fs.volName}"] = fs
|
57
|
-
end
|
58
|
-
unless fs.fsId.empty?
|
59
|
-
$log.debug "LinuxMount: adding \"UUID=#{fs.fsId}\" to fsSpecHash" if $log.debug?
|
60
|
-
fsSpecHash["UUID=#{fs.fsId}"] = fs
|
61
|
-
end
|
105
|
+
fs_spec_hash.merge!(add_fstab_entries(fs, v))
|
106
|
+
end
|
107
|
+
fs_spec_hash
|
108
|
+
end
|
62
109
|
|
63
|
-
|
64
|
-
|
65
|
-
# entries under /dev.
|
66
|
-
#
|
67
|
-
if v.dInfo.lvObj
|
68
|
-
lvName = v.dInfo.lvObj.lvName
|
69
|
-
vgName = v.dInfo.lvObj.vgObj.vgName
|
70
|
-
fsSpecHash["/dev/#{vgName}/#{lvName}"] = fs
|
71
|
-
fsSpecHash["/dev/mapper/#{vgName.gsub('-','--')}-#{lvName.gsub('-','--')}"] = fs
|
72
|
-
fsSpecHash["UUID=#{v.dInfo.lvObj.lvId}"] = fs
|
73
|
-
$log.debug "LinuxMount: Volume = #{v.dInfo.localDev}, partition = #{v.partNum} is a logical volume" if $log.debug?
|
74
|
-
next
|
75
|
-
end
|
110
|
+
def add_fstab_entries(fs, v)
|
111
|
+
fs_spec_hash = add_fstab_fs_entries(fs)
|
76
112
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
113
|
+
if v.dInfo.lvObj
|
114
|
+
fs_spec_hash.merge!(add_fstab_logical_entries(fs, v))
|
115
|
+
else
|
116
|
+
fs_spec_hash.merge!(add_fstab_physical_entry(fs, v))
|
117
|
+
end
|
118
|
+
fs_spec_hash
|
119
|
+
end
|
120
|
+
|
121
|
+
def add_fstab_fs_entries(fs)
|
122
|
+
#
|
123
|
+
# Specific file systems can be identified by fs UUID
|
124
|
+
# or file system volume label.
|
125
|
+
#
|
126
|
+
fs_spec_fs_hash = {}
|
127
|
+
unless fs.volName.empty?
|
128
|
+
$log.debug("LinuxMount: adding \"LABEL=#{fs.volName}\" & \"LABEL=/#{fs.volName}\" to hash") if $log.debug
|
129
|
+
fs_spec_fs_hash["LABEL=#{fs.volName}"] = fs
|
130
|
+
fs_spec_fs_hash["LABEL=/#{fs.volName}"] = fs
|
131
|
+
end
|
132
|
+
unless fs.fsId.empty?
|
133
|
+
$log.debug("LinuxMount: adding \"UUID=#{fs.fsId}\" to fs_spec_hash") if $log.debug
|
134
|
+
fs_spec_fs_hash["UUID=#{fs.fsId}"] = fs
|
135
|
+
end
|
136
|
+
fs_spec_fs_hash
|
137
|
+
end
|
138
|
+
|
139
|
+
def add_fstab_logical_entries(fs, v)
|
140
|
+
#
|
141
|
+
# Logical volumes can be identified by their lv specific
|
142
|
+
# entries under /dev.
|
143
|
+
#
|
144
|
+
lv_name = v.dInfo.lvObj.lvName
|
145
|
+
vg_name = v.dInfo.lvObj.vgObj.vgName
|
146
|
+
fs_spec_logical_hash = {}
|
147
|
+
fs_spec_logical_hash["/dev/#{vg_name}/#{lv_name}"] = fs
|
148
|
+
fs_spec_logical_hash["/dev/mapper/#{vg_name.gsub('-', '--')}-#{lv_name.gsub('-', '--')}"] = fs
|
149
|
+
fs_spec_logical_hash["UUID=#{v.dInfo.lvObj.lvId}"] = fs
|
150
|
+
$log.debug("LinuxMount: Volume = #{v.dInfo.localDev}, partition = #{v.partNum} is a logical volume") if $log.debug
|
151
|
+
fs_spec_logical_hash
|
152
|
+
end
|
153
|
+
|
154
|
+
def add_fstab_physical_entry(fs, v)
|
155
|
+
#
|
156
|
+
# Physical volumes are identified by entries under
|
157
|
+
# /dev based on OS hardware scan.
|
158
|
+
# TODO: support physical volume UUIDs
|
159
|
+
#
|
160
|
+
fs_spec_physical_hash = {}
|
161
|
+
$log.debug("LinuxMount: v.dInfo.hardwareId = #{v.dInfo.hardwareId}") if $log.debug
|
162
|
+
if v.partNum.zero?
|
163
|
+
fs_spec_physical_hash[@devHash[v.dInfo.hardwareId]] = fs
|
164
|
+
else
|
165
|
+
fs_spec_physical_hash[@devHash[v.dInfo.hardwareId] + v.partNum.to_s] = fs
|
88
166
|
end
|
167
|
+
fs_spec_physical_hash
|
168
|
+
end
|
89
169
|
|
170
|
+
def build_os_names
|
90
171
|
#
|
91
172
|
# Assign OS-specific names to all physical volumes.
|
92
173
|
#
|
@@ -99,79 +180,32 @@ module LinuxMount
|
|
99
180
|
end
|
100
181
|
@osNames[v.dInfo.hardwareId + ':' + v.partNum.to_s] = @devHash[v.dInfo.hardwareId] + v.partNum.to_s
|
101
182
|
end
|
183
|
+
end
|
102
184
|
|
185
|
+
def build_mount_point_tree(fs_spec_hash)
|
103
186
|
#
|
104
187
|
# Build a tree of file systems and their associated mont points.
|
105
188
|
#
|
106
189
|
root_added = false
|
107
190
|
@mountPoints = {}
|
108
|
-
$log.debug
|
191
|
+
$log.debug("LinuxMount: processing #{FSTAB_FILE_NAME}") if $log.debug
|
109
192
|
@rootFS.fileOpen(FSTAB_FILE_NAME, &:read).each_line do |fstl|
|
110
|
-
$log.debug
|
111
|
-
|
112
|
-
fsSpec, mtPoint = fstl.split(/\s+/)
|
113
|
-
$log.debug "LinuxMount: fsSpec: #{fsSpec}, mtPoint: #{mtPoint}" if $log.debug?
|
114
|
-
next if fsSpec == "none" || mtPoint == "swap"
|
115
|
-
next unless (fs = fsSpecHash[fsSpec])
|
116
|
-
$log.debug "LinuxMount: Adding fsSpec: #{fsSpec}, mtPoint: #{mtPoint}" if $log.debug?
|
117
|
-
addMountPoint(mtPoint, fs, fsSpec)
|
118
|
-
root_added = true if mtPoint == '/'
|
193
|
+
$log.debug("LinuxMount: fstab line: #{fstl}") if $log.debug
|
194
|
+
root_added = true if do_fstab_line(fstl, fs_spec_hash) == '/'
|
119
195
|
end
|
120
196
|
saveFs(@rootFS, "/", "ROOT") unless root_added
|
121
|
-
end # def fs_init
|
122
|
-
|
123
|
-
#
|
124
|
-
# Given a path to a file, return true if it's a symbolic link.
|
125
|
-
# Otherwise, return false.
|
126
|
-
#
|
127
|
-
def fileSymLink?(p)
|
128
|
-
#
|
129
|
-
# We can't just expand the links in the whole path,
|
130
|
-
# because then, the target file will no longer be a link.
|
131
|
-
# So, we expand the path to the target file, then open
|
132
|
-
# the target file through that path to obtain the link data.
|
133
|
-
#
|
134
|
-
np = normalizePath(p)
|
135
|
-
d = File.dirname(np)
|
136
|
-
f = File.basename(np)
|
137
|
-
|
138
|
-
# Expand the path to the target file.
|
139
|
-
exp_dir = expandLinks(d)
|
140
|
-
|
141
|
-
# Get the file system where the target file resides, and it's local path.
|
142
|
-
fs, lp = getFsPathBase(File.join(exp_dir, f))
|
143
|
-
(fs.fileSymLink?(lp))
|
144
197
|
end
|
145
198
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
#
|
152
|
-
|
153
|
-
|
154
|
-
# So, we expand the path to the target file, then open
|
155
|
-
# the target file through that path to obtain the link data.
|
156
|
-
#
|
157
|
-
np = normalizePath(p)
|
158
|
-
d = File.dirname(np)
|
159
|
-
f = File.basename(np)
|
160
|
-
|
161
|
-
# Expand the path to the target file.
|
162
|
-
exp_dir = expandLinks(d)
|
163
|
-
|
164
|
-
# Get the file system where the target file resides, and it's local path.
|
165
|
-
fs, lp = getFsPathBase(File.join(exp_dir, f))
|
166
|
-
# Read the link data from the file, through its file system.
|
167
|
-
sp = getSymLink(fs, lp)
|
168
|
-
# Construct and return the full path to the link target.
|
169
|
-
return(sp) if sp[0, 1] == '/'
|
170
|
-
(normalizePath(File.join(exp_dir, sp)))
|
199
|
+
def do_fstab_line(fstab_line, fs_spec_hash)
|
200
|
+
return if fstab_line =~ /^#.*$/ || fstab_line =~ /^\s*$/
|
201
|
+
fs_spec, mt_point = fstab_line.strip.split(/\s+/)
|
202
|
+
return if fs_spec == "none" || mt_point == "swap"
|
203
|
+
return unless (fs = fs_spec_hash[fs_spec])
|
204
|
+
$log.debug("LinuxMount: Adding fs_spec: #{fs_spec}, mt_point: #{mt_point}") if $log.debug
|
205
|
+
addMountPoint(mt_point, fs, fs_spec)
|
206
|
+
mt_point
|
171
207
|
end
|
172
208
|
|
173
|
-
private
|
174
|
-
|
175
209
|
def normalizePath(p)
|
176
210
|
# When running on windows, File.expand_path will add a drive letter.
|
177
211
|
# Remove it if it's there.
|
@@ -221,7 +255,7 @@ module LinuxMount
|
|
221
255
|
localPath = normalizePath(path)
|
222
256
|
end
|
223
257
|
|
224
|
-
|
258
|
+
getFsPathBase(expandLinks(localPath))
|
225
259
|
# getFsPathBase(path)
|
226
260
|
end
|
227
261
|
|
@@ -55,6 +55,11 @@ module MiqLinux
|
|
55
55
|
def parse_service(file)
|
56
56
|
debug "Parsing service unit: #{file}"
|
57
57
|
|
58
|
+
if duplicated_link?(file)
|
59
|
+
debug("#{file} is a soft link, skip to parse.")
|
60
|
+
return nil
|
61
|
+
end
|
62
|
+
|
58
63
|
unit = @fs.fileBasename(file)
|
59
64
|
name = unit.gsub(".service", "")
|
60
65
|
inif = ini(file)
|
@@ -92,6 +97,11 @@ module MiqLinux
|
|
92
97
|
def parse_target(file)
|
93
98
|
debug "Parsing target unit: #{file}"
|
94
99
|
|
100
|
+
if duplicated_link?(file)
|
101
|
+
debug("#{file} is a soft link, skip to parse.")
|
102
|
+
return nil
|
103
|
+
end
|
104
|
+
|
95
105
|
unit = @fs.fileBasename(file)
|
96
106
|
name = unit.gsub(".target", "")
|
97
107
|
inif = ini(file)
|
@@ -119,6 +129,10 @@ module MiqLinux
|
|
119
129
|
end
|
120
130
|
end
|
121
131
|
|
132
|
+
def duplicated_link?(file)
|
133
|
+
existing_dirs.any? { |dir| @fs.getLinkPath(file).start_with?("#{dir}/") } if @fs.fileSymLink?(file)
|
134
|
+
end
|
135
|
+
|
122
136
|
def debug(msg)
|
123
137
|
$log.debug msg if $log
|
124
138
|
end
|
@@ -6,12 +6,6 @@ module MiqWin32
|
|
6
6
|
class Software
|
7
7
|
attr_reader :applications, :patches, :product_keys
|
8
8
|
|
9
|
-
PRODUCT_KEY_MAPPING = [
|
10
|
-
'DigitalProductId', :product_key,
|
11
|
-
'ProductName', :name,
|
12
|
-
# 'ProductId', 'version',
|
13
|
-
]
|
14
|
-
|
15
9
|
PRODUCTS_MAPPING = [
|
16
10
|
'DisplayName', :name,
|
17
11
|
'Publisher', :vendor,
|
@@ -58,11 +52,30 @@ module MiqWin32
|
|
58
52
|
]
|
59
53
|
|
60
54
|
def initialize(_c, fs)
|
61
|
-
@applications = []
|
62
|
-
@
|
63
|
-
|
64
|
-
|
55
|
+
@patches = @applications = []
|
56
|
+
@patch_install_dates = @product_keys = {}
|
57
|
+
|
58
|
+
reg_doc = initialize_registry_doc(fs)
|
59
|
+
|
60
|
+
registry_applications(reg_doc)
|
61
|
+
registry_patches(reg_doc)
|
62
|
+
end
|
63
|
+
|
64
|
+
# # Process application images
|
65
|
+
# e.find_each("./descendant::image") { |i| nh[:image_md5] = i.attributes['md5']; validate_image(i, nh)}
|
66
|
+
#
|
67
|
+
# def self.validate_image(imageNode, nh)
|
68
|
+
# #logger.warn("MIQ(applications-add_elements): Checking application image [#{nh.inspect}] -- [#{imageNode.to_s}]")
|
69
|
+
# x = ApplicationImage.find_by_md5(imageNode.attributes['md5'])
|
70
|
+
# if x
|
71
|
+
# #logger.warn("MIQ(applications-add_elements): Application image found [#{imageNode.attributes['md5']}]")
|
72
|
+
# else
|
73
|
+
# #logger.warn("MIQ(applications-add_elements): Application image NOT found [#{imageNode.attributes['md5']}]")
|
74
|
+
# ApplicationImage.create({:md5=>imageNode.attributes['md5'], :name=>nh['name'], :vendor=>nh['vendor'], :version=>nh['version']})
|
75
|
+
# end
|
76
|
+
# end
|
65
77
|
|
78
|
+
def initialize_registry_doc(fs)
|
66
79
|
regHnd = RemoteRegistry.new(fs, true)
|
67
80
|
# reg_doc = regHnd.loadHive("software", ["Microsoft"])
|
68
81
|
reg_doc = regHnd.loadHive('software',
|
@@ -80,160 +93,144 @@ module MiqWin32
|
|
80
93
|
regHnd.close
|
81
94
|
|
82
95
|
@product_keys = collectProductKeys(@digital_product_keys)
|
96
|
+
reg_doc
|
97
|
+
end
|
83
98
|
|
99
|
+
def registry_applications(registry_doc)
|
84
100
|
# Get the applications
|
85
|
-
reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData",
|
86
|
-
if reg_node
|
87
|
-
reg_node.each_element_with_attribute(:keyname) do |users|
|
88
|
-
users.each_element_with_attribute(:keyname) do |components|
|
89
|
-
if components.attributes[:keyname].downcase == "products"
|
90
|
-
components.each_element_with_attribute(:keyname) do |products|
|
91
|
-
attrs = XmlFind.decode(products, PRODUCTS_MAPPING)
|
92
|
-
attrs.merge!(:typename => "win32_product", :product_key => @product_keys[attrs[:name]])
|
93
|
-
clean_up_path(attrs)
|
94
|
-
@applications << attrs
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
+
reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData", registry_doc.root)
|
102
|
+
registry_applications_user_data(reg_node) if reg_node
|
101
103
|
["HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\App Paths",
|
102
104
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths"].each do |reg_path|
|
103
|
-
|
104
|
-
if reg_node
|
105
|
-
postProcessApps(reg_node, fs)
|
106
|
-
reg_node.each_element_with_attribute(:keyname) do |e|
|
107
|
-
attrs = XmlFind.decode(e, APP_PATHS_MAPPING)
|
108
|
-
next if attrs[:name].nil?
|
109
|
-
attrs.merge!(:typename => "app_path", :product_key => @product_keys[attrs[:name]])
|
110
|
-
clean_up_path(attrs)
|
111
|
-
@applications << attrs unless isDupApp?(attrs)
|
112
|
-
end
|
113
|
-
end
|
105
|
+
registry_applications_app_paths(registry_doc, reg_path)
|
114
106
|
end
|
115
|
-
|
116
107
|
["HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
|
117
108
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"].each do |reg_path|
|
118
|
-
reg_node = MIQRexml.findRegElement(reg_path,
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
109
|
+
reg_node = MIQRexml.findRegElement(reg_path, registry_doc.root)
|
110
|
+
reg_node&.each_element_with_attribute(:keyname) do |e|
|
111
|
+
registry_applications_uninstall(e)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def registry_applications_user_data(reg_node)
|
117
|
+
reg_node.each_element_with_attribute(:keyname) do |users|
|
118
|
+
users.each_element_with_attribute(:keyname) do |components|
|
119
|
+
next unless components.attributes[:keyname].downcase == "products"
|
120
|
+
components.each_element_with_attribute(:keyname) do |products|
|
121
|
+
add_applications(PRODUCTS_MAPPING, "win32_product", products)
|
131
122
|
end
|
132
123
|
end
|
133
124
|
end
|
125
|
+
end
|
134
126
|
|
135
|
-
|
136
|
-
reg_node = MIQRexml.findRegElement(
|
137
|
-
reg_node
|
138
|
-
|
127
|
+
def registry_applications_app_paths(registry_doc, registry_path)
|
128
|
+
return unless (reg_node = MIQRexml.findRegElement(registry_path, registry_doc.root))
|
129
|
+
postProcessApps(reg_node, fs)
|
130
|
+
reg_node.each_element_with_attribute(:keyname) do |e|
|
131
|
+
add_applications(APP_PATHS_MAPPING, "app_path", e)
|
132
|
+
end
|
133
|
+
end
|
139
134
|
|
140
|
-
|
141
|
-
|
142
|
-
|
135
|
+
def add_applications(mapping, type_name, element)
|
136
|
+
return if (attrs = XmlFind.decode(element, mapping))[:name].nil?
|
137
|
+
attrs[:typename] = type_name; attrs[:product_key] = @product_keys[attrs[:name]]
|
138
|
+
clean_up_path(attrs)
|
139
|
+
@applications << attrs unless isDupApp?(attrs)
|
140
|
+
end
|
143
141
|
|
144
|
-
|
145
|
-
|
142
|
+
def registry_applications_uninstall(element)
|
143
|
+
return if (attrs = XmlFind.decode(element, UNINSTALL_MAPPING))[:name].nil?
|
144
|
+
if ["security update", "update"].include?(attrs.delete(:release_type).to_s.downcase)
|
145
|
+
@patch_install_dates[e.attributes[:keyname]] = Time.parse.getlocal(attrs[:installed_on]) unless attrs[:installed_on].nil?
|
146
|
+
return
|
147
|
+
else
|
148
|
+
attrs.delete(:installed_on)
|
146
149
|
end
|
150
|
+
attrs[:typename] = "uninstall"; attrs[:product_key] = @product_keys[attrs[:name]]
|
151
|
+
@applications << attrs unless isDupApp?(attrs)
|
152
|
+
end
|
147
153
|
|
154
|
+
def registry_patches(registry_doc)
|
155
|
+
# Get the patches (Win2000, Win2003, WinXP)
|
156
|
+
reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix", registry_doc.root)
|
157
|
+
reg_node&.each_element_with_attribute(:keyname) do |e|
|
158
|
+
registry_patches_hotfixes(e)
|
159
|
+
end
|
148
160
|
# Get the patches (Vista, Win2008, Windows 7)
|
149
|
-
reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\Packages",
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
next if e.attributes.nil? || e.attributes[:keyname].nil?
|
154
|
-
if e.attributes[:keyname][0, 8] == 'Package_'
|
155
|
-
# Expected pattern: Package_for_KBxxx_RTM~xxxx
|
156
|
-
|
157
|
-
# Get the hotfix id (KB #) out of the keyname
|
158
|
-
package = e.attributes[:keyname].split("_")
|
159
|
-
|
160
|
-
# If the package identifier starts with KB, use this
|
161
|
-
# otherwise grab the ID from the end of the string (if it's long enough)
|
162
|
-
hotfix_id = nil
|
163
|
-
if (package[2][0, 2] == 'KB')
|
164
|
-
hotfix_id = package[2]
|
165
|
-
elsif package.size >= 4
|
166
|
-
hotfix_id = package[3]
|
167
|
-
else
|
168
|
-
# Unknown package ID pattern, print this out
|
169
|
-
str = ''
|
170
|
-
e.write(str)
|
171
|
-
$log.warn "Win32Software::initialize - Can't determine patch element's hotfix id: #{str}"
|
172
|
-
end
|
173
|
-
# don't add this package if the ID is nil
|
174
|
-
next if hotfix_id.nil?
|
175
|
-
|
176
|
-
hotfix_id = hotfix_id.split('~')[0]
|
177
|
-
|
178
|
-
unless hotfix.key?(hotfix_id)
|
179
|
-
attrs = XmlFind.decode(e, HOTFIX_MAPPING_VISTA)
|
180
|
-
install_time = wtime2time(attrs[:install_time_high], attrs[:install_time_low])
|
181
|
-
@patches << {:name => hotfix_id, :vendor => "Microsoft Corporation", :installed_on => install_time, :installed => 1}
|
182
|
-
hotfix[hotfix_id] = true
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
161
|
+
reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\Packages", registry_doc.root)
|
162
|
+
hotfix = {}
|
163
|
+
reg_node&.each_element do |e|
|
164
|
+
registry_patches_packages(hotfix, e)
|
186
165
|
end
|
187
166
|
end
|
188
167
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
# x = ApplicationImage.find_by_md5(imageNode.attributes['md5'])
|
195
|
-
# if x
|
196
|
-
# #logger.warn("MIQ(applications-add_elements): Application image found [#{imageNode.attributes['md5']}]")
|
197
|
-
# else
|
198
|
-
# #logger.warn("MIQ(applications-add_elements): Application image NOT found [#{imageNode.attributes['md5']}]")
|
199
|
-
# ApplicationImage.create({:md5=>imageNode.attributes['md5'], :name=>nh['name'], :vendor=>nh['vendor'], :version=>nh['version']})
|
200
|
-
# end
|
201
|
-
# end
|
168
|
+
def registry_patches_hotfixes(element)
|
169
|
+
attrs = XmlFind.decode(element, HOTFIX_MAPPING)
|
170
|
+
# Check both descriptions and take the first one with a value
|
171
|
+
attrs.delete(:description2) if attrs[:description] || attrs[:description2].blank?
|
172
|
+
attrs[:description] = attrs.delete(:description2) if attrs[:description2]
|
202
173
|
|
203
|
-
|
204
|
-
|
205
|
-
applicationsToXml(doc)
|
206
|
-
patchesToXml(doc)
|
207
|
-
doc
|
174
|
+
attrs.merge!(:name => element.attributes[:keyname], :vendor => "Microsoft Corporation", :installed_on => @patch_install_dates[element.attributes[:keyname]]) unless element.attributes.nil? || element.attributes[:keyname].nil?
|
175
|
+
@patches << attrs
|
208
176
|
end
|
209
177
|
|
210
|
-
def
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
178
|
+
def registry_patches_packages(hotfix, element)
|
179
|
+
return if element.attributes.nil? || element.attributes[:keyname].nil?
|
180
|
+
if element.attributes[:keyname][0, 8] == 'Package_'
|
181
|
+
# don't add this package if the ID is nil
|
182
|
+
return if (hotfix_id = hotfix_id(e)).nil?
|
183
|
+
|
184
|
+
hotfix[hotfix_id] ||=
|
185
|
+
begin
|
186
|
+
attrs = XmlFind.decode(element, HOTFIX_MAPPING_VISTA)
|
187
|
+
install_time = wtime2time(attrs[:install_time_high], attrs[:install_time_low])
|
188
|
+
@patches << {:name => hotfix_id, :vendor => "Microsoft Corporation", :installed_on => install_time, :installed => 1}
|
189
|
+
true
|
190
|
+
end
|
215
191
|
end
|
216
|
-
doc
|
217
192
|
end
|
218
193
|
|
219
|
-
def
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
194
|
+
def hotfix_id(element)
|
195
|
+
# Expected pattern: Package_for_KBxxx_RTM~xxxx
|
196
|
+
# Get the hotfix id (KB #) out of the keyname
|
197
|
+
package = element.attributes[:keyname].split("_")
|
198
|
+
# If the package identifier starts with KB, use this
|
199
|
+
# otherwise grab the ID from the end of the string (if it's long enough)
|
200
|
+
if package[2][0, 2] == 'KB'
|
201
|
+
hotfix_id = package[2]
|
202
|
+
elsif package.size >= 4
|
203
|
+
hotfix_id = package[3]
|
204
|
+
else
|
205
|
+
# Unknown package ID pattern, print this out
|
206
|
+
str = ''
|
207
|
+
element.write(str)
|
208
|
+
$log.warn("Win32Software::initialize - Can't determine patch element's hotfix id: #{str}")
|
224
209
|
end
|
210
|
+
hotfix_id.split('~')[0] unless hotfix_id.nil?
|
211
|
+
end
|
212
|
+
|
213
|
+
def to_xml(doc = nil)
|
214
|
+
doc ||= MiqXml.createDoc(nil)
|
215
|
+
element_to_xml(doc, @applications, "applications", "application")
|
216
|
+
element_to_xml(doc, @patches, "patches", "patch")
|
225
217
|
doc
|
226
218
|
end
|
227
219
|
|
228
|
-
def
|
229
|
-
|
220
|
+
def element_to_xml(doc = nil, software_type, doc_element, node_element)
|
221
|
+
doc ||= MiqXml.createDoc(nil)
|
222
|
+
return doc if software_type.empty?
|
223
|
+
node = doc.add_element(doc_element)
|
224
|
+
software_type.each { |a| node.add_element(node_element, XmlHelpers.stringify_keys(a)) }
|
225
|
+
doc
|
230
226
|
end
|
231
227
|
|
232
|
-
def
|
228
|
+
def isDupApp?(attrs)
|
229
|
+
clean_up_path(attrs)
|
233
230
|
@applications.each do |app|
|
234
|
-
return
|
231
|
+
return true if app[:name] == attrs[:name]
|
235
232
|
end
|
236
|
-
|
233
|
+
false
|
237
234
|
end
|
238
235
|
|
239
236
|
def clean_up_path(attrs)
|
@@ -264,7 +261,6 @@ module MiqWin32
|
|
264
261
|
next if appNode.text.nil?
|
265
262
|
# st = Time.now
|
266
263
|
|
267
|
-
fh = nil
|
268
264
|
fileName = appNode.text
|
269
265
|
fileName.tr!("\\", "/")
|
270
266
|
fileName = fileName[1..-2] if fileName[0, 1] == "\"" && fileName[-1, 1] == "\""
|
@@ -316,8 +312,7 @@ module MiqWin32
|
|
316
312
|
def wtime2time(high_time, low_time)
|
317
313
|
th = [high_time.to_i].pack('L').unpack('L')[0] << 32
|
318
314
|
tl = [low_time.to_i].pack('L').unpack('L')[0]
|
319
|
-
time_int = ((th + tl) - 116444736000000000) / 10000000
|
320
|
-
return nil if time_int < 0
|
315
|
+
return nil if (time_int = ((th + tl) - 116444736000000000) / 10000000) < 0
|
321
316
|
Time.at(time_int).getutc rescue nil
|
322
317
|
end
|
323
318
|
end # Class Software
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: manageiq-smartstate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ManageIQ Developers
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: azure-armrest
|