manageiq-smartstate 0.2.10 → 0.2.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|