idrac 0.7.1 → 0.7.2
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/README.md +13 -0
- data/bin/idrac +374 -93
- data/lib/idrac/boot.rb +186 -79
- data/lib/idrac/client.rb +95 -0
- data/lib/idrac/jobs.rb +8 -4
- data/lib/idrac/license.rb +325 -39
- data/lib/idrac/lifecycle.rb +88 -2
- data/lib/idrac/power.rb +22 -63
- data/lib/idrac/storage.rb +275 -115
- data/lib/idrac/system.rb +227 -130
- data/lib/idrac/system_config.rb +163 -139
- data/lib/idrac/utility.rb +60 -0
- data/lib/idrac/version.rb +1 -1
- data/lib/idrac/virtual_media.rb +19 -29
- data/lib/idrac.rb +2 -0
- metadata +3 -2
data/bin/idrac
CHANGED
@@ -121,7 +121,8 @@ module IDRAC
|
|
121
121
|
map "lifecycle:status" => :lifecycle_status
|
122
122
|
def lifecycle_status
|
123
123
|
with_idrac_client do |client|
|
124
|
-
client.get_lifecycle_status
|
124
|
+
status = client.get_lifecycle_status
|
125
|
+
puts "Lifecycle Controller is #{status ? 'Enabled'.green : 'Disabled'.red}"
|
125
126
|
end
|
126
127
|
end
|
127
128
|
|
@@ -335,6 +336,75 @@ module IDRAC
|
|
335
336
|
end
|
336
337
|
end
|
337
338
|
|
339
|
+
desc "sessions_show", "Show active iDRAC sessions"
|
340
|
+
map "sessions:show" => :sessions_show
|
341
|
+
def sessions_show
|
342
|
+
with_idrac_client do |client|
|
343
|
+
begin
|
344
|
+
sessions_url = client.session.send(:determine_session_endpoint)
|
345
|
+
puts "Retrieving sessions from: #{sessions_url}".light_yellow if options[:debug]
|
346
|
+
|
347
|
+
response = client.authenticated_request(:get, sessions_url)
|
348
|
+
|
349
|
+
if response.status == 200
|
350
|
+
sessions_data = JSON.parse(response.body)
|
351
|
+
if sessions_data['Members'] && sessions_data['Members'].any?
|
352
|
+
puts "Active iDRAC Sessions: #{sessions_data['Members'].count}".green.bold
|
353
|
+
|
354
|
+
# Get details for each session
|
355
|
+
sessions_data['Members'].each_with_index do |session, index|
|
356
|
+
session_url = session['@odata.id']
|
357
|
+
puts "Retrieving session details from: #{session_url}".light_yellow if options[:debug]
|
358
|
+
|
359
|
+
session_response = client.authenticated_request(:get, session_url)
|
360
|
+
|
361
|
+
if session_response.status == 200
|
362
|
+
session_detail = JSON.parse(session_response.body)
|
363
|
+
puts "Session #{index + 1}:".light_cyan
|
364
|
+
puts " ID: #{session_detail['Id']}".light_cyan
|
365
|
+
puts " Username: #{session_detail['UserName']}".light_cyan
|
366
|
+
puts " Created: #{session_detail['Created']}".light_cyan
|
367
|
+
else
|
368
|
+
puts "Session #{index + 1}: Unable to retrieve details (Status: #{session_response.status})".light_red
|
369
|
+
end
|
370
|
+
end
|
371
|
+
else
|
372
|
+
puts "No active sessions found".yellow
|
373
|
+
end
|
374
|
+
else
|
375
|
+
puts "Failed to retrieve sessions. Status code: #{response.status}".red
|
376
|
+
puts "Error response: #{response.body[0..200]}...".light_red if response.body && !response.body.empty?
|
377
|
+
end
|
378
|
+
rescue Faraday::ConnectionFailed => e
|
379
|
+
puts "Connection to iDRAC failed: #{e.message}".red
|
380
|
+
rescue JSON::ParserError => e
|
381
|
+
puts "Failed to parse iDRAC response: #{e.message}".red
|
382
|
+
rescue => e
|
383
|
+
puts "Error: #{e.message}".red
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
desc "sessions_clear", "Clear all iDRAC sessions"
|
389
|
+
map "sessions:clear" => :sessions_clear
|
390
|
+
def sessions_clear
|
391
|
+
with_idrac_client do |client|
|
392
|
+
begin
|
393
|
+
puts "Attempting to clear all iDRAC sessions...".yellow
|
394
|
+
if client.session.force_clear_sessions
|
395
|
+
puts "Successfully cleared all iDRAC sessions".green
|
396
|
+
else
|
397
|
+
puts "Failed to clear iDRAC sessions".red
|
398
|
+
puts "You may need to manually delete sessions through the iDRAC web interface".yellow
|
399
|
+
end
|
400
|
+
rescue Faraday::ConnectionFailed => e
|
401
|
+
puts "Connection to iDRAC failed: #{e.message}".red
|
402
|
+
rescue => e
|
403
|
+
puts "Error: #{e.message}".red
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
338
408
|
desc "power_state", "Get current server power state"
|
339
409
|
map "power:state" => :power_state
|
340
410
|
def power_state
|
@@ -384,11 +454,11 @@ module IDRAC
|
|
384
454
|
license = client.license_info
|
385
455
|
if license
|
386
456
|
puts "\nLicense Information:".green.bold
|
387
|
-
puts "Description: #{license
|
388
|
-
puts "License Type: #{license
|
457
|
+
puts "Description: #{license["Description"]}".cyan
|
458
|
+
puts "License Type: #{license["LicenseType"]}".cyan
|
389
459
|
puts "License Version: #{client.license_version || 'Unknown'}".cyan
|
390
|
-
puts "Removable: #{license
|
391
|
-
puts "Status: #{license
|
460
|
+
puts "Removable: #{license["Removable"]}".cyan
|
461
|
+
puts "Status: #{license["Status"] && license["Status"]["Health"] || 'Unknown'}".cyan
|
392
462
|
else
|
393
463
|
puts "No license information available".yellow
|
394
464
|
end
|
@@ -437,8 +507,8 @@ module IDRAC
|
|
437
507
|
|
438
508
|
# Storage
|
439
509
|
{ name: "Storage Controller", method: -> (c) { c.controller } },
|
440
|
-
{ name: "Physical Drives", method: -> (c) { controller = c.controller; c.drives(controller) } },
|
441
|
-
{ name: "Virtual Disks", method: -> (c) { controller = c.controller; c.volumes(controller) } },
|
510
|
+
{ name: "Physical Drives", method: -> (c) { controller = c.controller; c.drives(controller["@odata.id"]) } },
|
511
|
+
{ name: "Virtual Disks", method: -> (c) { controller = c.controller; c.volumes(controller["@odata.id"]) } },
|
442
512
|
|
443
513
|
# System components
|
444
514
|
{ name: "Memory Info", method: -> (c) { c.memory } },
|
@@ -553,14 +623,29 @@ module IDRAC
|
|
553
623
|
# Storage commands
|
554
624
|
desc "storage_controller", "Get storage controller information"
|
555
625
|
map "storage:controller" => :storage_controller
|
626
|
+
method_option :name_pattern, type: :string, desc: "Filter controllers by name pattern (defaults to PERC)"
|
627
|
+
method_option :prefer_most_drives_by_count, type: :boolean, default: false, desc: "Prefer controller with the most drives"
|
628
|
+
method_option :prefer_most_drives_by_size, type: :boolean, default: false, desc: "Prefer controller with the largest total drive capacity"
|
556
629
|
def storage_controller
|
557
630
|
with_idrac_client do |client|
|
558
|
-
|
631
|
+
find_controller_args = {}
|
632
|
+
find_controller_args[:name_pattern] = options[:name_pattern] if options[:name_pattern]
|
633
|
+
find_controller_args[:prefer_most_drives_by_count] = options[:prefer_most_drives_by_count]
|
634
|
+
find_controller_args[:prefer_most_drives_by_size] = options[:prefer_most_drives_by_size]
|
635
|
+
|
636
|
+
controller = client.find_controller(**find_controller_args)
|
637
|
+
|
638
|
+
if !controller
|
639
|
+
puts "No storage controllers found".red
|
640
|
+
return
|
641
|
+
end
|
642
|
+
|
559
643
|
puts "\nStorage Controller Summary:".green.bold
|
560
|
-
puts "Name: #{controller
|
561
|
-
puts "Model: #{controller
|
562
|
-
puts "Health: #{controller
|
563
|
-
puts "Manufacturer: #{controller
|
644
|
+
puts "Name: #{controller["name"]}".cyan
|
645
|
+
puts "Model: #{controller["model"]}".cyan
|
646
|
+
puts "Health: #{controller["status"] || 'Unknown'}".cyan
|
647
|
+
puts "Manufacturer: #{controller["manufacturer"]}".cyan
|
648
|
+
puts "Drives: #{controller["drives_count"]}".cyan
|
564
649
|
|
565
650
|
if client.controller_encryption_capable?(controller)
|
566
651
|
puts "Encryption Capable: Yes".green
|
@@ -581,17 +666,17 @@ module IDRAC
|
|
581
666
|
puts "-" * 80
|
582
667
|
|
583
668
|
controllers.each do |controller|
|
584
|
-
puts "Controller: #{controller
|
585
|
-
puts " Model: #{controller
|
586
|
-
puts " Status: #{controller
|
587
|
-
puts " Drives: #{controller
|
588
|
-
puts " Firmware: #{controller
|
589
|
-
puts " Type: #{controller
|
590
|
-
puts " PCI Slot: #{controller
|
669
|
+
puts "Controller: #{controller["name"]}".cyan.bold
|
670
|
+
puts " Model: #{controller["model"]}"
|
671
|
+
puts " Status: #{controller["status"]}"
|
672
|
+
puts " Drives: #{controller["drives_count"]}"
|
673
|
+
puts " Firmware: #{controller["firmware_version"]}"
|
674
|
+
puts " Type: #{controller["controller_type"]}"
|
675
|
+
puts " PCI Slot: #{controller["pci_slot"]}"
|
591
676
|
|
592
|
-
if controller
|
593
|
-
puts " Encryption: #{controller
|
594
|
-
puts " Encryption Mode: #{controller
|
677
|
+
if controller["encryption_capability"]
|
678
|
+
puts " Encryption: #{controller["encryption_capability"]}"
|
679
|
+
puts " Encryption Mode: #{controller["encryption_mode"] || 'Disabled'}"
|
595
680
|
end
|
596
681
|
|
597
682
|
puts
|
@@ -601,26 +686,43 @@ module IDRAC
|
|
601
686
|
end
|
602
687
|
end
|
603
688
|
|
604
|
-
desc "storage_drives", "Get physical drive information"
|
689
|
+
desc "storage_drives", "Get physical drive information across all controllers"
|
605
690
|
map "storage:drives" => :storage_drives
|
691
|
+
method_option :name_pattern, type: :string, desc: "Filter controllers by name pattern (defaults to PERC)"
|
692
|
+
method_option :prefer_most_drives_by_count, type: :boolean, default: false, desc: "Prefer controller with more drives"
|
693
|
+
method_option :prefer_most_drives_by_size, type: :boolean, default: false, desc: "Prefer controller with the largest total drive capacity"
|
606
694
|
def storage_drives
|
607
695
|
with_idrac_client do |client|
|
608
|
-
|
609
|
-
|
696
|
+
find_controller_args = {}
|
697
|
+
find_controller_args[:name_pattern] = options[:name_pattern] if options[:name_pattern]
|
698
|
+
find_controller_args[:prefer_most_drives_by_count] = options[:prefer_most_drives_by_count]
|
699
|
+
find_controller_args[:prefer_most_drives_by_size] = options[:prefer_most_drives_by_size]
|
700
|
+
|
701
|
+
controller = client.find_controller(**find_controller_args)
|
702
|
+
|
703
|
+
if !controller
|
704
|
+
puts "No storage controllers found".red
|
705
|
+
return
|
706
|
+
end
|
707
|
+
|
708
|
+
drives = client.drives(controller["@odata.id"])
|
610
709
|
|
611
710
|
puts "\nPhysical Drives (#{drives.size}):".green.bold
|
612
711
|
drives.each do |drive|
|
613
|
-
capacity_gb = drive
|
614
|
-
health_color = drive
|
712
|
+
capacity_gb = drive["capacity_bytes"].to_f / (1024**3)
|
713
|
+
health_color = drive["health"] == "OK" ? :green : :red
|
615
714
|
|
616
|
-
puts "#{drive
|
617
|
-
puts " Model: #{drive
|
618
|
-
puts " Health: #{drive
|
715
|
+
puts "#{drive["name"]}:".bold
|
716
|
+
puts " Model: #{drive["model"]}".cyan
|
717
|
+
puts " Health: #{drive["health"].send(health_color)}"
|
619
718
|
puts " Capacity: #{capacity_gb.round(2)} GB".cyan
|
620
|
-
puts " Media Type: #{drive
|
621
|
-
|
622
|
-
|
623
|
-
|
719
|
+
puts " Media Type: #{drive["media_type"]}".cyan
|
720
|
+
if drive["life_left_percent"]
|
721
|
+
puts " Life Left: #{drive["life_left_percent"]}%".cyan
|
722
|
+
end
|
723
|
+
puts " Serial: #{drive["serial"]}".cyan
|
724
|
+
if drive["encryption_ability"]
|
725
|
+
puts " Encryption: #{drive["encryption_ability"]}".cyan
|
624
726
|
end
|
625
727
|
puts ""
|
626
728
|
end
|
@@ -629,53 +731,84 @@ module IDRAC
|
|
629
731
|
|
630
732
|
desc "storage_volumes", "Get virtual disk information"
|
631
733
|
map "storage:volumes" => :storage_volumes
|
734
|
+
method_option :name_pattern, type: :string, desc: "Filter controllers by name pattern (defaults to PERC)"
|
735
|
+
method_option :prefer_most_drives_by_count, type: :boolean, default: false, desc: "Prefer controller with the most drives"
|
736
|
+
method_option :prefer_most_drives_by_size, type: :boolean, default: false, desc: "Prefer controller with the largest total drive capacity"
|
632
737
|
def storage_volumes
|
633
738
|
with_idrac_client do |client|
|
634
|
-
|
635
|
-
|
739
|
+
find_controller_args = {}
|
740
|
+
find_controller_args[:name_pattern] = options[:name_pattern] if options[:name_pattern]
|
741
|
+
find_controller_args[:prefer_most_drives_by_count] = options[:prefer_most_drives_by_count]
|
742
|
+
find_controller_args[:prefer_most_drives_by_size] = options[:prefer_most_drives_by_size]
|
743
|
+
|
744
|
+
controller = client.find_controller(**find_controller_args)
|
745
|
+
|
746
|
+
if !controller
|
747
|
+
puts "No storage controllers found".red
|
748
|
+
return
|
749
|
+
end
|
750
|
+
|
751
|
+
volumes = client.volumes(controller["@odata.id"])
|
636
752
|
|
637
753
|
puts "\nVirtual Disks (#{volumes.size}):".green.bold
|
638
754
|
volumes.each do |volume|
|
639
|
-
capacity_gb = volume
|
640
|
-
health_color = volume
|
755
|
+
capacity_gb = volume["capacity_bytes"].to_f / (1024**3)
|
756
|
+
health_color = volume["health"] == "OK" ? :green : :yellow
|
641
757
|
|
642
|
-
puts "#{volume
|
643
|
-
puts " RAID Type: #{volume
|
644
|
-
puts " Health: #{volume
|
758
|
+
puts "#{volume["name"]}:".bold
|
759
|
+
puts " RAID Type: #{volume["raid_level"] || volume["volume_type"]}".cyan
|
760
|
+
puts " Health: #{volume["health"].send(health_color)}"
|
645
761
|
puts " Capacity: #{capacity_gb.round(2)} GB".cyan
|
646
|
-
puts " Stripe Size: #{volume
|
647
|
-
puts " Read Cache: #{volume
|
648
|
-
puts " Write Cache: #{volume
|
649
|
-
puts " FastPath: #{volume
|
650
|
-
puts " Encrypted: #{volume
|
762
|
+
puts " Stripe Size: #{volume["stripe_size"]}".cyan
|
763
|
+
puts " Read Cache: #{volume["read_cache_policy"]}".cyan
|
764
|
+
puts " Write Cache: #{volume["write_cache_policy"]}".cyan
|
765
|
+
puts " FastPath: #{volume["fastpath"] == 'enabled' ? 'Enabled'.green : 'Disabled'.yellow}"
|
766
|
+
puts " Encrypted: #{volume["encrypted"] ? 'Yes'.green : 'No'.yellow}" if volume["encrypted"] != nil
|
651
767
|
|
652
|
-
if volume
|
653
|
-
puts " Progress: #{volume
|
654
|
-
puts " Operation: #{volume
|
768
|
+
if volume["progress"]
|
769
|
+
puts " Progress: #{volume["progress"]}%".cyan
|
770
|
+
puts " Operation: #{volume["message"]}".cyan
|
655
771
|
end
|
656
772
|
puts ""
|
657
773
|
end
|
658
774
|
end
|
659
775
|
end
|
660
776
|
|
661
|
-
desc "storage_create_volume", "Create a new virtual disk"
|
777
|
+
desc "storage_create_volume", "Create a new virtual disk, requires a controller"
|
662
778
|
map "storage:create_volume" => :storage_create_volume
|
779
|
+
map "storage:create:volume" => :storage_create_volume
|
663
780
|
method_option :name, type: :string, default: "vssd0", desc: "Volume name"
|
664
781
|
method_option :raid, type: :string, default: "RAID5", desc: "RAID type (RAID0, RAID1, RAID5, RAID6, RAID10)"
|
782
|
+
method_option :y, type: :boolean, default: false, desc: "Automatically confirm operation without prompting"
|
665
783
|
def storage_create_volume
|
666
784
|
with_idrac_client do |client|
|
667
|
-
|
668
|
-
|
785
|
+
# Use find_controller instead of controller
|
786
|
+
controller = client.find_controller
|
787
|
+
|
788
|
+
if !controller
|
789
|
+
puts "No storage controllers found".red
|
790
|
+
return
|
791
|
+
end
|
792
|
+
|
793
|
+
# Print system identification information
|
794
|
+
print_system_identification(client, "storage")
|
669
795
|
|
670
|
-
|
796
|
+
drives = client.drives(controller["@odata.id"])
|
797
|
+
|
798
|
+
# Confirm with the user before proceeding, unless -y is specified
|
671
799
|
puts "This will create a new #{options[:raid]} volume named '#{options[:name]}' using #{drives.size} drives.".yellow
|
672
800
|
puts "All data on these drives will be lost!".red.bold
|
673
801
|
|
674
|
-
|
675
|
-
|
802
|
+
if options[:y]
|
803
|
+
puts "Automatically confirming operation (-y flag provided)".yellow
|
804
|
+
confirmation = 'y'
|
805
|
+
else
|
806
|
+
print "Do you want to continue? (y/n): "
|
807
|
+
confirmation = $stdin.gets.chomp.downcase
|
808
|
+
end
|
676
809
|
|
677
810
|
if confirmation == 'y'
|
678
|
-
client.create_virtual_disk(controller.
|
811
|
+
client.create_virtual_disk(controller_id: controller["@odata.id"], drives: drives, name: options[:name], raid_type: options[:raid])
|
679
812
|
puts "Volume created successfully".green
|
680
813
|
else
|
681
814
|
puts "Operation cancelled".yellow
|
@@ -685,45 +818,52 @@ module IDRAC
|
|
685
818
|
|
686
819
|
desc "storage_delete_volume", "Delete a virtual disk"
|
687
820
|
map "storage:delete_volume" => :storage_delete_volume
|
821
|
+
method_option :y, type: :boolean, default: false, desc: "Automatically confirm operation without prompting"
|
688
822
|
def storage_delete_volume
|
689
823
|
with_idrac_client do |client|
|
690
|
-
|
691
|
-
|
824
|
+
# Use find_controller instead of controller
|
825
|
+
controller = client.find_controller
|
692
826
|
|
693
|
-
if
|
694
|
-
puts "No
|
827
|
+
if !controller
|
828
|
+
puts "No storage controllers found".red
|
695
829
|
return
|
696
830
|
end
|
697
831
|
|
698
|
-
|
699
|
-
|
700
|
-
|
832
|
+
# Print system identification information
|
833
|
+
print_system_identification(client, "storage")
|
834
|
+
|
835
|
+
volumes = client.volumes(controller["@odata.id"])
|
836
|
+
|
837
|
+
if volumes.empty?
|
838
|
+
puts "No volumes found".red
|
839
|
+
return
|
701
840
|
end
|
702
841
|
|
703
|
-
|
704
|
-
input = $stdin.gets.chomp
|
842
|
+
volume_to_delete = volumes.find { |v| v["Id"] == options[:id] }
|
705
843
|
|
706
|
-
if
|
707
|
-
|
844
|
+
if volume_to_delete.nil?
|
845
|
+
volume_ids = volumes.map { |v| v["Id"] }.join(", ")
|
846
|
+
puts "Volume with ID #{options[:id]} not found".red
|
847
|
+
puts "Available volume IDs: #{volume_ids}".yellow
|
708
848
|
return
|
709
849
|
end
|
710
850
|
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
puts "
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
851
|
+
puts "This will delete volume '#{volume_to_delete["Name"]}' (ID: #{volume_to_delete["Id"]})".yellow
|
852
|
+
puts "All data on this volume will be lost!".red.bold
|
853
|
+
|
854
|
+
if options[:y]
|
855
|
+
puts "Automatically confirming operation (-y flag provided)".yellow
|
856
|
+
confirmation = 'y'
|
857
|
+
else
|
858
|
+
print "Do you want to continue? (y/n): "
|
859
|
+
confirmation = $stdin.gets.chomp.downcase
|
860
|
+
end
|
861
|
+
|
862
|
+
if confirmation == 'y'
|
863
|
+
client.delete_virtual_disk(volume_to_delete["@odata.id"])
|
864
|
+
puts "Volume deleted successfully".green
|
725
865
|
else
|
726
|
-
puts "
|
866
|
+
puts "Operation cancelled".yellow
|
727
867
|
end
|
728
868
|
end
|
729
869
|
end
|
@@ -732,10 +872,19 @@ module IDRAC
|
|
732
872
|
map "storage:encryption_enable" => :storage_encryption_enable
|
733
873
|
method_option :passphrase, type: :string, desc: "Encryption passphrase"
|
734
874
|
method_option :keyid, type: :string, desc: "Key identifier"
|
875
|
+
method_option :y, type: :boolean, default: false, desc: "Automatically confirm operation without prompting"
|
735
876
|
def storage_encryption_enable
|
736
877
|
with_idrac_client do |client|
|
737
|
-
controller = client.
|
738
|
-
|
878
|
+
controller = client.find_controller
|
879
|
+
|
880
|
+
if !controller
|
881
|
+
puts "No storage controllers found".red
|
882
|
+
return
|
883
|
+
end
|
884
|
+
|
885
|
+
print_system_identification(client, "storage encryption")
|
886
|
+
|
887
|
+
drives = client.drives(controller["@odata.id"])
|
739
888
|
|
740
889
|
if !client.controller_encryption_capable?(controller)
|
741
890
|
puts "This controller does not support encryption".red
|
@@ -755,6 +904,10 @@ module IDRAC
|
|
755
904
|
# Get passphrase if not provided
|
756
905
|
passphrase = options[:passphrase]
|
757
906
|
if passphrase.nil?
|
907
|
+
if options[:y]
|
908
|
+
puts "Error: With -y flag, you must provide a passphrase with --passphrase".red
|
909
|
+
return
|
910
|
+
end
|
758
911
|
print "Enter encryption passphrase (min 8 characters): "
|
759
912
|
passphrase = $stdin.noecho(&:gets).chomp
|
760
913
|
puts
|
@@ -763,16 +916,38 @@ module IDRAC
|
|
763
916
|
# Get keyid if not provided
|
764
917
|
keyid = options[:keyid] || "RAID-Key-#{Time.now.strftime('%Y%m%d')}"
|
765
918
|
|
766
|
-
|
919
|
+
if options[:y]
|
920
|
+
puts "Automatically confirming operation (-y flag provided)".yellow
|
921
|
+
else
|
922
|
+
puts "About to enable encryption using key ID: #{keyid}".yellow
|
923
|
+
print "Do you want to continue? (y/n): "
|
924
|
+
confirmation = $stdin.gets.chomp.downcase
|
925
|
+
if confirmation != 'y'
|
926
|
+
puts "Operation cancelled".yellow
|
927
|
+
return
|
928
|
+
end
|
929
|
+
end
|
930
|
+
|
931
|
+
client.enable_local_key_management(controller_id: controller["@odata.id"], passphrase: passphrase, key_id: keyid)
|
767
932
|
puts "Encryption enabled successfully".green
|
768
933
|
end
|
769
934
|
end
|
770
935
|
|
771
936
|
desc "storage_encryption_disable", "Disable Self-Encrypting Drive (SED) support"
|
772
937
|
map "storage:encryption_disable" => :storage_encryption_disable
|
938
|
+
method_option :y, type: :boolean, default: false, desc: "Automatically confirm operation without prompting"
|
773
939
|
def storage_encryption_disable
|
774
940
|
with_idrac_client do |client|
|
775
|
-
controller = client.
|
941
|
+
controller = client.find_controller
|
942
|
+
|
943
|
+
if !controller
|
944
|
+
puts "No storage controllers found".red
|
945
|
+
return
|
946
|
+
end
|
947
|
+
|
948
|
+
print_system_identification(client, "storage encryption")
|
949
|
+
|
950
|
+
drives = client.drives(controller["@odata.id"])
|
776
951
|
|
777
952
|
if !client.controller_encryption_enabled?(controller)
|
778
953
|
puts "Encryption is not enabled on this controller".yellow
|
@@ -780,11 +955,17 @@ module IDRAC
|
|
780
955
|
end
|
781
956
|
|
782
957
|
puts "WARNING: Disabling encryption may prevent access to encrypted data!".red.bold
|
783
|
-
|
784
|
-
|
958
|
+
|
959
|
+
if options[:y]
|
960
|
+
puts "Automatically confirming operation (-y flag provided)".yellow
|
961
|
+
confirmation = 'DISABLE'
|
962
|
+
else
|
963
|
+
print "Type 'DISABLE' to confirm: "
|
964
|
+
confirmation = $stdin.gets.chomp
|
965
|
+
end
|
785
966
|
|
786
967
|
if confirmation == 'DISABLE'
|
787
|
-
client.disable_local_key_management(controller.
|
968
|
+
client.disable_local_key_management(controller["@odata.id"])
|
788
969
|
puts "Encryption disabled successfully".green
|
789
970
|
else
|
790
971
|
puts "Operation cancelled".yellow
|
@@ -905,6 +1086,7 @@ module IDRAC
|
|
905
1086
|
puts " #{port['name']}:".bold
|
906
1087
|
puts " Status: #{port['status'].send(status_color)}"
|
907
1088
|
puts " MAC: #{port['mac']}".cyan
|
1089
|
+
puts " IP Address: #{port['ip_address'] || 'Not assigned'}".cyan
|
908
1090
|
puts " Speed: #{port['speed_mbps']} Mbps".cyan
|
909
1091
|
if port['pci']
|
910
1092
|
puts " PCI Bus: #{port['pci']}".cyan
|
@@ -1085,6 +1267,7 @@ module IDRAC
|
|
1085
1267
|
|
1086
1268
|
desc "boot_power_optimization", "Configure BIOS for OS-controlled power management"
|
1087
1269
|
map "boot:power_optimization" => :boot_power_optimization
|
1270
|
+
map "boot:power:optimization" => :boot_power_optimization
|
1088
1271
|
def boot_power_optimization
|
1089
1272
|
with_idrac_client do |client|
|
1090
1273
|
client.set_bios_os_power_control
|
@@ -1282,13 +1465,13 @@ module IDRAC
|
|
1282
1465
|
# Storage tests
|
1283
1466
|
puts "\n[TEST] Storage management".cyan.bold
|
1284
1467
|
begin
|
1285
|
-
controller = client.
|
1286
|
-
puts "✓ Storage controller: #{controller
|
1468
|
+
controller = client.find_controller
|
1469
|
+
puts "✓ Storage controller: #{controller["name"]} (#{controller["model"]})".green
|
1287
1470
|
|
1288
|
-
drives = client.drives(controller)
|
1471
|
+
drives = client.drives(controller["@odata.id"])
|
1289
1472
|
puts "✓ Found #{drives.size} physical drives".green
|
1290
1473
|
|
1291
|
-
volumes = client.volumes(controller)
|
1474
|
+
volumes = client.volumes(controller["@odata.id"])
|
1292
1475
|
puts "✓ Found #{volumes.size} virtual disks".green
|
1293
1476
|
test_results["storage"] = { status: "PASS", message: "Retrieved storage information successfully" }
|
1294
1477
|
rescue => e
|
@@ -1424,6 +1607,59 @@ module IDRAC
|
|
1424
1607
|
end
|
1425
1608
|
end
|
1426
1609
|
|
1610
|
+
desc "storage_raid_status", "Get storage RAID status"
|
1611
|
+
map "storage:raid_status" => :storage_raid_status
|
1612
|
+
def storage_raid_status
|
1613
|
+
with_idrac_client do |client|
|
1614
|
+
# Print system identification information
|
1615
|
+
print_system_identification(client, "storage", false)
|
1616
|
+
|
1617
|
+
controller = client.find_controller
|
1618
|
+
|
1619
|
+
if !controller
|
1620
|
+
puts "No storage controllers found".red
|
1621
|
+
return
|
1622
|
+
end
|
1623
|
+
|
1624
|
+
puts "Storage Controller: #{controller["Name"]} (#{controller["Model"]})".green
|
1625
|
+
|
1626
|
+
# Disks
|
1627
|
+
disks = client.drives(controller["@odata.id"])
|
1628
|
+
|
1629
|
+
puts "\nPhysical Disks (#{disks.size}):"
|
1630
|
+
if disks.empty?
|
1631
|
+
puts " No physical disks found".yellow
|
1632
|
+
else
|
1633
|
+
disks.each do |disk|
|
1634
|
+
status_color = disk["MediaType"] == "SSD" ? :green : :blue
|
1635
|
+
capacity = disk["CapacityBytes"] ? "#{disk["CapacityBytes"] / (1024**3)} GB" : "Unknown"
|
1636
|
+
puts " #{disk["Id"] || disk["name"] || "Unknown"}: #{disk["Name"] || disk["name"] || "Unknown"} (#{disk["MediaType"] || "Unknown"}, #{capacity})".send(status_color)
|
1637
|
+
end
|
1638
|
+
end
|
1639
|
+
|
1640
|
+
# Volumes
|
1641
|
+
volumes = client.volumes(controller["@odata.id"])
|
1642
|
+
|
1643
|
+
puts "\nVirtual Disks (#{volumes.size}):"
|
1644
|
+
if volumes.empty?
|
1645
|
+
puts " No virtual disks found".yellow
|
1646
|
+
else
|
1647
|
+
volumes.each do |vol|
|
1648
|
+
puts " #{vol["Id"]}: #{vol["Name"]} (#{vol["RAIDType"]}, #{vol["CapacityBytes"] / (1024**3)} GB)".green
|
1649
|
+
end
|
1650
|
+
end
|
1651
|
+
end
|
1652
|
+
end
|
1653
|
+
|
1654
|
+
desc "idrac_reset", "Reset the iDRAC controller (graceful restart)"
|
1655
|
+
map "idrac:reset" => :idrac_reset
|
1656
|
+
def idrac_reset
|
1657
|
+
with_idrac_client do |client|
|
1658
|
+
result = client.reset!
|
1659
|
+
puts result ? "iDRAC reset completed successfully" : "iDRAC reset failed"
|
1660
|
+
end
|
1661
|
+
end
|
1662
|
+
|
1427
1663
|
private
|
1428
1664
|
|
1429
1665
|
def with_idrac_client
|
@@ -1484,6 +1720,51 @@ module IDRAC
|
|
1484
1720
|
retry_delay: options[:retry_delay]
|
1485
1721
|
)
|
1486
1722
|
end
|
1723
|
+
|
1724
|
+
# Get system identification information (service tag, model, iDRAC IP)
|
1725
|
+
# @param client [IDRAC::Client] The iDRAC client
|
1726
|
+
# @return [Hash] System identification information
|
1727
|
+
def get_system_identification(client)
|
1728
|
+
# Get system information
|
1729
|
+
system_info = client.get_basic_system_info rescue { model: "Unknown Model", sku: "Unknown" }
|
1730
|
+
|
1731
|
+
# Get iDRAC network info
|
1732
|
+
begin
|
1733
|
+
idrac_net = client.idrac_network
|
1734
|
+
idrac_ip = idrac_net["ipv4"]
|
1735
|
+
rescue
|
1736
|
+
idrac_ip = "Unknown IP"
|
1737
|
+
end
|
1738
|
+
|
1739
|
+
{
|
1740
|
+
service_tag: system_info[:sku],
|
1741
|
+
model: system_info[:model],
|
1742
|
+
idrac_ip: idrac_ip
|
1743
|
+
}
|
1744
|
+
end
|
1745
|
+
|
1746
|
+
# Print system identification information
|
1747
|
+
# @param client [IDRAC::Client] The iDRAC client
|
1748
|
+
# @param component_type [String] The type of operation (e.g., "storage", "encryption")
|
1749
|
+
# @param require_confirmation [Boolean] Whether to require confirmation
|
1750
|
+
# @return [Hash] System identification information
|
1751
|
+
def print_system_identification(client, component_type, require_confirmation = true)
|
1752
|
+
system_id = get_system_identification(client)
|
1753
|
+
|
1754
|
+
# Display system context
|
1755
|
+
puts "\nWARNING: About to modify #{component_type} on:".red.bold
|
1756
|
+
puts " Service Tag: #{system_id[:service_tag]}".yellow
|
1757
|
+
puts " Dell Model: #{system_id[:model]}".yellow
|
1758
|
+
puts " iDRAC IP: #{system_id[:idrac_ip]}".yellow
|
1759
|
+
puts
|
1760
|
+
|
1761
|
+
# Require confirmation if needed
|
1762
|
+
if require_confirmation && !options[:y]
|
1763
|
+
exit unless yes?("Continue? (y/n) ")
|
1764
|
+
end
|
1765
|
+
|
1766
|
+
system_id
|
1767
|
+
end
|
1487
1768
|
end
|
1488
1769
|
end
|
1489
1770
|
|