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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dd6c8e7fc62f55e3496569ccfb9b7154401a3f1c
4
- data.tar.gz: aa6b6c308e48258d4ce2f4a502907d1747332980
3
+ metadata.gz: 62cf3e30f6bab25afc33edb03fe30b6849f3ae29
4
+ data.tar.gz: caec40acfd2c105763fa1144faaf3b4d4f7710f0
5
5
  SHA512:
6
- metadata.gz: e1ef8e9e1f61e45418d4fef638e4b021a0e5e80b3e6701af800f46b6f695d316cfc23ea3bc10526c623b781961d22a44fe7a8691ff76e33cb833b8d8503176da
7
- data.tar.gz: 242e3b1c155fca702a7fc3987c169299bcd240fb2012adc87f6ea778d340f257ba80eceebf37e8919235f6d48ad9bfd2011f07af5172e3ef606700e009450e4a
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)
@@ -269,7 +269,7 @@ module Ext3
269
269
  names.shift
270
270
 
271
271
  dir = ifs_getDirR(names, miqfs)
272
- raise "Directory '#{p}' not found" if dir.nil?
272
+ $log.info("Directory '#{p}' not found") if dir.nil?
273
273
  dir
274
274
  end
275
275
 
@@ -280,7 +280,7 @@ module ReiserFS
280
280
  names.shift
281
281
 
282
282
  dir = ifs_getDirR(names, miqfs)
283
- raise "Directory '#{p}' not found" if dir.nil?
283
+ $log.info("Directory '#{p}' not found") if dir.nil?
284
284
  dir
285
285
  end
286
286
 
@@ -264,7 +264,7 @@ module XFS
264
264
  names.shift
265
265
 
266
266
  dir = ifs_getDirR(names, miqfs)
267
- raise "Directory '#{p}' not found" if dir.nil?
267
+ $log.info("Directory '#{p}' not found") if dir.nil?
268
268
  dir
269
269
  end
270
270
 
@@ -147,7 +147,7 @@ module Ext3
147
147
 
148
148
  # /////////////////////////////////////////////////////////////////////////
149
149
  # // initialize
150
- attr_reader :numGroups, :fsId, :stream, :numBlocks, :numInodes, :fsId, :volName
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 = @sb['fs_state']
173
- raise "Ext3::Superblock.initialize: Invalid file system state" if state > FSS_END
174
- if state != FSS_CLEAN
175
- $log.warn("Ext3 file system has errors") if $log && gotBit?(state, FSS_ERR)
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
@@ -142,14 +142,13 @@ module Ext4
142
142
 
143
143
  # /////////////////////////////////////////////////////////////////////////
144
144
  # // initialize
145
- attr_reader :numGroups, :fsId, :stream, :numBlocks, :numInodes, :fsId, :volName
146
- attr_reader :sectorSize, :blockSize, :groupDescriptorSize
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 = @sb['fs_state']
161
- raise "Ext4::Superblock.initialize: Invalid file system state" if state > FSS_END
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 = 'a'
19
- ideMap = {"ide0:0" => "a", "ide0:1" => "b", "ide1:0" => "c", "ide1:1" => "d"}
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
- fsSpecHash = {}
95
+ fs_spec_hash = {}
36
96
  @volumes.each do |v|
37
- $log.debug "LinuxMount: Volume = #{v.dInfo.localDev} (#{v.dInfo.hardwareId}, partition = #{v.partNum})" if $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
- unless (fs = MiqFS.getFS(v))
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
- # Specific file systems can be identified by fs UUID
50
- # or file system volume label.
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
- # Logical volumes can be identified by their lv specific
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
- # Physical volumes are identified by entries under
79
- # /dev based on OS hardware scan.
80
- # TODO: support physical volume UUIDs
81
- #
82
- $log.debug "LinuxMount: v.dInfo.hardwareId = #{v.dInfo.hardwareId}" if $log.debug?
83
- if v.partNum == 0
84
- fsSpecHash[@devHash[v.dInfo.hardwareId]] = fs
85
- else
86
- fsSpecHash[@devHash[v.dInfo.hardwareId] + v.partNum.to_s] = fs
87
- end
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 "LinuxMount: processing #{FSTAB_FILE_NAME}" if $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 "LinuxMount: fstab line: #{fstl}" if $log.debug?
111
- next if fstl =~ /^#.*$/ || fstl =~ /^\s*$/
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
- # Given a path to a symbolic link, return the full
148
- # path to where the link points.
149
- #
150
- def getLinkPath(p)
151
- #
152
- # We can't just expand the links in the whole path,
153
- # because then, the target file will no longer be a link.
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
- p = getFsPathBase(expandLinks(localPath))
258
+ getFsPathBase(expandLinks(localPath))
225
259
  # getFsPathBase(path)
226
260
  end
227
261
 
@@ -1,5 +1,5 @@
1
1
  module ManageIQ
2
2
  module Smartstate
3
- VERSION = "0.2.10".freeze
3
+ VERSION = "0.2.11".freeze
4
4
  end
5
5
  end
@@ -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
- @patches = []
63
- @product_keys = {}
64
- @patch_install_dates = {}
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", reg_doc.root)
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
- reg_node = MIQRexml.findRegElement(reg_path, reg_doc.root)
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, reg_doc.root)
119
- if reg_node
120
- reg_node.each_element_with_attribute(:keyname) do |e|
121
- attrs = XmlFind.decode(e, UNINSTALL_MAPPING)
122
- next if attrs[:name].nil?
123
- if ["security update", "update"].include?(attrs.delete(:release_type).to_s.downcase)
124
- @patch_install_dates[e.attributes[:keyname]] = Time.parse(attrs[:installed_on]) unless attrs[:installed_on].nil?
125
- next
126
- else
127
- attrs.delete(:installed_on)
128
- end
129
- attrs.merge!(:typename => "uninstall", :product_key => @product_keys[attrs[:name]])
130
- @applications << attrs unless isDupApp?(attrs)
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
- # Get the patches (Win2000, Win2003, WinXP)
136
- reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix", reg_doc.root)
137
- reg_node&.each_element_with_attribute(:keyname) do |e|
138
- attrs = XmlFind.decode(e, HOTFIX_MAPPING)
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
- # Check both descriptions and take the first one with a value
141
- attrs.delete(:description2) if attrs[:description] || attrs[:description2].blank?
142
- attrs[:description] = attrs.delete(:description2) if attrs[:description2]
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
- attrs.merge!(:name => e.attributes[:keyname], :vendor => "Microsoft Corporation", :installed_on => @patch_install_dates[e.attributes[:keyname]]) unless e.attributes.nil? || e.attributes[:keyname].nil?
145
- @patches << attrs
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", reg_doc.root)
150
- if reg_node
151
- hotfix = {}
152
- reg_node.each_element do |e|
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
- # # Process application images
190
- # e.find_each("./descendant::image") { |i| nh[:image_md5] = i.attributes['md5']; validate_image(i, nh)}
191
- #
192
- # def self.validate_image(imageNode, nh)
193
- # #logger.warn("MIQ(applications-add_elements): Checking application image [#{nh.inspect}] -- [#{imageNode.to_s}]")
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
- def to_xml(doc = nil)
204
- doc = MiqXml.createDoc(nil) unless doc
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 applicationsToXml(doc = nil)
211
- doc = MiqXml.createDoc(nil) unless doc
212
- unless @applications.empty?
213
- node = doc.add_element("applications")
214
- @applications.each { |a| node.add_element("application", XmlHelpers.stringify_keys(a)) }
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 patchesToXml(doc = nil)
220
- doc = MiqXml.createDoc(nil) unless doc
221
- unless @patches.empty?
222
- node = doc.add_element("patches")
223
- @patches.each { |p| node.add_element("patch", XmlHelpers.stringify_keys(p)) }
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 isDupApp?(attrs)
229
- findDupApp(attrs) ? true : false
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 findDupApp(attrs)
228
+ def isDupApp?(attrs)
229
+ clean_up_path(attrs)
233
230
  @applications.each do |app|
234
- return app if app[:name] == attrs[:name]
231
+ return true if app[:name] == attrs[:name]
235
232
  end
236
- nil
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.10
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-03-02 00:00:00.000000000 Z
11
+ date: 2018-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: azure-armrest