idrac 0.1.28 → 0.1.30
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 +24 -1
- data/bin/idrac +80 -51
- data/dell_firmware_downloads/Catalog.etag +1 -0
- data/dell_firmware_downloads/Catalog.xml +0 -0
- data/idrac-0.1.6/.rspec +3 -0
- data/idrac-0.1.6/README.md +103 -0
- data/idrac-0.1.6/Rakefile +17 -0
- data/idrac-0.1.6/bin/console +11 -0
- data/idrac-0.1.6/bin/idrac +179 -0
- data/idrac-0.1.6/bin/setup +8 -0
- data/idrac-0.1.6/idrac.gemspec +51 -0
- data/idrac-0.1.6/lib/idrac/client.rb +109 -0
- data/idrac-0.1.6/lib/idrac/firmware.rb +366 -0
- data/idrac-0.1.6/lib/idrac/version.rb +5 -0
- data/idrac-0.1.6/lib/idrac.rb +30 -0
- data/idrac-0.1.6/sig/idrac.rbs +4 -0
- data/idrac-0.1.7/.rspec +3 -0
- data/idrac-0.1.7/README.md +103 -0
- data/idrac-0.1.7/Rakefile +17 -0
- data/idrac-0.1.7/bin/console +11 -0
- data/idrac-0.1.7/bin/idrac +179 -0
- data/idrac-0.1.7/bin/setup +8 -0
- data/idrac-0.1.7/idrac.gemspec +51 -0
- data/idrac-0.1.7/lib/idrac/client.rb +109 -0
- data/idrac-0.1.7/lib/idrac/firmware.rb +366 -0
- data/idrac-0.1.7/lib/idrac/screenshot.rb +49 -0
- data/idrac-0.1.7/lib/idrac/version.rb +5 -0
- data/idrac-0.1.7/lib/idrac.rb +30 -0
- data/idrac-0.1.7/sig/idrac.rbs +4 -0
- data/idrac.gemspec +1 -0
- data/idrac.py +500 -0
- data/lib/idrac/client.rb +206 -144
- data/lib/idrac/firmware.rb +272 -62
- data/lib/idrac/firmware_catalog.rb +131 -59
- data/lib/idrac/version.rb +1 -1
- data/test_firmware_update.rb +68 -0
- data/updater.rb +729 -0
- metadata +45 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6992752c6eee7bfb3c858d8bb465c68c68bff2008732ecfc88553ba7ac0524b5
|
4
|
+
data.tar.gz: ab1e816e1c1d903c3095c5131652f917a61b3c4006e0941fd05d24555230f9f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b65362922f5a5728e6840a005ee7a79f2c08a835bba4ae7394eb304d2992426d9a9a52457173eb579e8e792413767c9249c64f5eacaee9dd47105971b10b3187
|
7
|
+
data.tar.gz: 8f97a86b72b0fb3544cb85c61f94b8228b037f63adeb345d9da856f7159d7e698c176fd303e212182dd779496b77c07b0b2efe83cc8d8fe8cee281060132d0e0
|
data/README.md
CHANGED
@@ -7,7 +7,11 @@ A Ruby client for the Dell iDRAC API. This gem provides a command-line interface
|
|
7
7
|
- Take screenshots of the iDRAC console
|
8
8
|
- Update firmware using Dell's catalog
|
9
9
|
- Check for firmware updates
|
10
|
-
- Interactive firmware update process
|
10
|
+
- Interactive firmware update process with robust error handling
|
11
|
+
- Simplified catalog download without requiring host connection
|
12
|
+
- Comprehensive error handling with clear user guidance
|
13
|
+
- Automatic job tracking and monitoring for firmware updates
|
14
|
+
- Color-coded terminal output for improved readability and user experience
|
11
15
|
|
12
16
|
## Installation
|
13
17
|
|
@@ -130,6 +134,25 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
130
134
|
|
131
135
|
## Changelog
|
132
136
|
|
137
|
+
### Version 0.1.30
|
138
|
+
- **Enhanced Terminal Output with Colors**: Added colorized output for better readability and user experience
|
139
|
+
- Integrated the `colorize` gem to provide color-coded messages throughout the application
|
140
|
+
- Success messages are displayed in green, warnings in yellow, errors in red, and informational messages in cyan
|
141
|
+
- Improved visual distinction between different types of messages (success, error, warning, info)
|
142
|
+
- Enhanced readability of firmware update status, system information, and error messages
|
143
|
+
- Updated all output messages across the codebase for consistent color formatting
|
144
|
+
- Added color to the test script output for better visualization of the firmware update process
|
145
|
+
|
146
|
+
### Version 0.1.29
|
147
|
+
- **Enhanced Firmware Update Error Handling**: Improved detection and handling of common firmware update issues
|
148
|
+
- Added specific error handling for "deployment already in progress" scenarios with clear user guidance
|
149
|
+
- Improved job ID extraction with fallback mechanisms to ensure proper job tracking
|
150
|
+
- Enhanced the `upload_firmware` method to properly initiate firmware updates by calling the SimpleUpdate action
|
151
|
+
- Added informative messages before starting firmware updates, including iDRAC limitations and requirements
|
152
|
+
- Simplified the catalog download process by removing host requirement from the `firmware:catalog` command
|
153
|
+
- Added a comprehensive test script (`test_firmware_update.rb`) to demonstrate the firmware update process
|
154
|
+
- Improved user experience with better error messages and recovery suggestions for common issues
|
155
|
+
|
133
156
|
### Version 0.1.28
|
134
157
|
- **Improved Firmware Update Checking**: Completely redesigned the firmware update checking process
|
135
158
|
- Added a dedicated `FirmwareCatalog` class for better separation of concerns
|
data/bin/idrac
CHANGED
@@ -10,27 +10,12 @@ end
|
|
10
10
|
# Load required gems directly
|
11
11
|
require "thor"
|
12
12
|
require "idrac"
|
13
|
+
require "colorize"
|
13
14
|
|
14
15
|
module IDRAC
|
15
|
-
# Standalone catalog command that doesn't require a host
|
16
|
-
class CatalogCommand < Thor
|
17
|
-
desc "download [DIRECTORY]", "Download Dell firmware catalog"
|
18
|
-
def download(directory = nil)
|
19
|
-
# Create a FirmwareCatalog instance
|
20
|
-
catalog = IDRAC::FirmwareCatalog.new
|
21
|
-
|
22
|
-
begin
|
23
|
-
catalog_path = catalog.download(directory)
|
24
|
-
puts "Catalog downloaded to: #{catalog_path}"
|
25
|
-
rescue IDRAC::Error => e
|
26
|
-
puts "Error: #{e.message}"
|
27
|
-
exit 1
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
16
|
class CLI < Thor
|
33
|
-
|
17
|
+
# Make host not required for all commands
|
18
|
+
class_option :host, type: :string, required: false, desc: "iDRAC host address"
|
34
19
|
class_option :username, type: :string, required: false, default: "root", desc: "iDRAC username (default: root)"
|
35
20
|
class_option :password, type: :string, required: false, default: "calvin", desc: "iDRAC password (default: calvin)"
|
36
21
|
class_option :port, type: :numeric, default: 443, desc: "iDRAC port"
|
@@ -42,6 +27,9 @@ module IDRAC
|
|
42
27
|
method_option :wait, type: :boolean, default: true, desc: "Wait for the update to complete"
|
43
28
|
method_option :timeout, type: :numeric, default: 3600, desc: "Timeout in seconds when waiting"
|
44
29
|
def firmware_update(path)
|
30
|
+
# Ensure host is provided for commands that need it
|
31
|
+
ensure_host_provided
|
32
|
+
|
45
33
|
check_ssl_verification
|
46
34
|
client = create_client
|
47
35
|
firmware = IDRAC::Firmware.new(client)
|
@@ -59,13 +47,26 @@ module IDRAC
|
|
59
47
|
|
60
48
|
desc "firmware:catalog [DIRECTORY]", "Download Dell firmware catalog"
|
61
49
|
def firmware_catalog(directory = nil)
|
62
|
-
#
|
63
|
-
|
50
|
+
# This command doesn't require a host
|
51
|
+
# Create a FirmwareCatalog instance directly
|
52
|
+
catalog = IDRAC::FirmwareCatalog.new
|
53
|
+
|
54
|
+
begin
|
55
|
+
puts "Downloading Dell catalog...".yellow
|
56
|
+
catalog_path = catalog.download(directory)
|
57
|
+
puts "Catalog downloaded to: #{catalog_path}".green
|
58
|
+
rescue IDRAC::Error => e
|
59
|
+
puts "Error: #{e.message}".red.bold
|
60
|
+
exit 1
|
61
|
+
end
|
64
62
|
end
|
65
63
|
|
66
64
|
desc "firmware:status", "Show current firmware status and available updates"
|
67
65
|
method_option :catalog, type: :string, desc: "Path to existing catalog file"
|
68
66
|
def firmware_status
|
67
|
+
# Ensure host is provided for commands that need it
|
68
|
+
ensure_host_provided
|
69
|
+
|
69
70
|
check_ssl_verification
|
70
71
|
client = create_client
|
71
72
|
firmware = IDRAC::Firmware.new(client)
|
@@ -74,15 +75,15 @@ module IDRAC
|
|
74
75
|
# Get system inventory - the Firmware class will print its own message
|
75
76
|
inventory = firmware.get_system_inventory
|
76
77
|
|
77
|
-
puts "System Information:"
|
78
|
-
puts " Model: #{inventory[:system][:model]}"
|
79
|
-
puts " Manufacturer: #{inventory[:system][:manufacturer]}"
|
80
|
-
puts " Service Tag: #{inventory[:system][:service_tag]}"
|
81
|
-
puts " BIOS Version: #{inventory[:system][:bios_version]}"
|
78
|
+
puts "System Information:".green.bold
|
79
|
+
puts " Model: #{inventory[:system][:model]}".light_cyan
|
80
|
+
puts " Manufacturer: #{inventory[:system][:manufacturer]}".light_cyan
|
81
|
+
puts " Service Tag: #{inventory[:system][:service_tag]}".light_cyan
|
82
|
+
puts " BIOS Version: #{inventory[:system][:bios_version]}".light_cyan
|
82
83
|
|
83
|
-
puts "\nInstalled Firmware:"
|
84
|
+
puts "\nInstalled Firmware:".green.bold
|
84
85
|
inventory[:firmware].each do |fw|
|
85
|
-
puts " #{fw[:name]}: #{fw[:version]} (#{fw[:updateable] ? 'Updateable' : 'Not Updateable'})"
|
86
|
+
puts " #{fw[:name]}: #{fw[:version]} (#{fw[:updateable] ? 'Updateable'.light_green : 'Not Updateable'.light_red})".light_cyan
|
86
87
|
end
|
87
88
|
|
88
89
|
# Default catalog location is now ~/.idrac/Catalog.xml
|
@@ -96,13 +97,13 @@ module IDRAC
|
|
96
97
|
updates = firmware.check_updates(catalog_path)
|
97
98
|
|
98
99
|
if updates.empty?
|
99
|
-
puts "
|
100
|
+
puts "\nNo updates available.".yellow
|
100
101
|
end
|
101
102
|
else
|
102
|
-
puts "\nTo check for updates, download the catalog first with 'idrac catalog
|
103
|
+
puts "\nTo check for updates, download the catalog first with 'idrac firmware:catalog'".yellow
|
103
104
|
end
|
104
105
|
rescue IDRAC::Error => e
|
105
|
-
puts "Error: #{e.message}"
|
106
|
+
puts "Error: #{e.message}".red.bold
|
106
107
|
exit 1
|
107
108
|
ensure
|
108
109
|
client.logout
|
@@ -112,6 +113,9 @@ module IDRAC
|
|
112
113
|
desc "firmware:interactive", "Interactive firmware update"
|
113
114
|
method_option :catalog, type: :string, desc: "Path to existing catalog file"
|
114
115
|
def firmware_interactive
|
116
|
+
# Ensure host is provided for commands that need it
|
117
|
+
ensure_host_provided
|
118
|
+
|
115
119
|
check_ssl_verification
|
116
120
|
client = create_client
|
117
121
|
firmware = IDRAC::Firmware.new(client)
|
@@ -129,14 +133,42 @@ module IDRAC
|
|
129
133
|
|
130
134
|
# If still no catalog, download it
|
131
135
|
if catalog_path.nil?
|
132
|
-
puts "No catalog found. Downloading..."
|
136
|
+
puts "No catalog found. Downloading...".yellow
|
133
137
|
catalog = IDRAC::FirmwareCatalog.new
|
134
138
|
catalog_path = catalog.download
|
135
139
|
end
|
136
140
|
|
137
|
-
firmware.
|
138
|
-
|
139
|
-
puts "
|
141
|
+
puts "Starting interactive firmware update. Please note:".green.bold
|
142
|
+
puts "- The iDRAC can only process one firmware update at a time".light_cyan
|
143
|
+
puts "- Updates may take several minutes to complete".light_cyan
|
144
|
+
puts "- For BIOS updates, a server reboot will be required to apply the update".light_cyan
|
145
|
+
puts "- If you encounter errors, check the iDRAC web interface for active jobs".light_cyan
|
146
|
+
puts ""
|
147
|
+
|
148
|
+
begin
|
149
|
+
firmware.interactive_update(catalog_path)
|
150
|
+
rescue ArgumentError => e
|
151
|
+
puts "Error: #{e.message}".red.bold
|
152
|
+
puts "This could be due to an issue with the interactive update process.".yellow
|
153
|
+
puts "If you're seeing a 'job ID not found' error, it might be because:".yellow
|
154
|
+
puts "1. The firmware update job wasn't created properly".light_yellow
|
155
|
+
puts "2. There's already an update in progress".light_yellow
|
156
|
+
puts "3. The iDRAC needs time to process the previous request".light_yellow
|
157
|
+
puts "\nTry again in a few minutes or check the iDRAC web interface for active jobs.".light_cyan
|
158
|
+
rescue IDRAC::Error => e
|
159
|
+
if e.message.include?("already in progress")
|
160
|
+
puts "Error: #{e.message}".red.bold
|
161
|
+
puts "\nTroubleshooting steps:".yellow.bold
|
162
|
+
puts "1. Check the iDRAC web interface under Maintenance > System Update for active jobs".light_yellow
|
163
|
+
puts "2. Wait for any existing updates to complete (can take 15-30 minutes)".light_yellow
|
164
|
+
puts "3. If no updates appear to be in progress, you may need to restart the iDRAC".light_yellow
|
165
|
+
puts " (iDRAC web interface > Settings > iDRAC Settings > Reset iDRAC)".light_yellow
|
166
|
+
else
|
167
|
+
puts "Error: #{e.message}".red.bold
|
168
|
+
end
|
169
|
+
end
|
170
|
+
rescue => e
|
171
|
+
puts "Error: #{e.message}".red.bold
|
140
172
|
exit 1
|
141
173
|
ensure
|
142
174
|
client.logout
|
@@ -146,6 +178,9 @@ module IDRAC
|
|
146
178
|
desc "screenshot", "Take a screenshot of the current iDRAC console"
|
147
179
|
method_option :output, type: :string, desc: "Output filename (default: idrac_screenshot_timestamp.png)"
|
148
180
|
def screenshot
|
181
|
+
# Ensure host is provided for commands that need it
|
182
|
+
ensure_host_provided
|
183
|
+
|
149
184
|
check_ssl_verification
|
150
185
|
client = create_client
|
151
186
|
|
@@ -177,11 +212,18 @@ module IDRAC
|
|
177
212
|
|
178
213
|
private
|
179
214
|
|
215
|
+
def ensure_host_provided
|
216
|
+
unless options[:host]
|
217
|
+
puts "Error: No value provided for required option '--host'".red.bold
|
218
|
+
exit 1
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
180
222
|
def check_ssl_verification
|
181
223
|
# If verify_ssl is not explicitly set in the command line, show a warning
|
182
224
|
unless ARGV.include?('--verify-ssl') || ARGV.include?('--no-verify-ssl')
|
183
|
-
puts "WARNING: SSL verification is disabled by default. iDRAC typically uses self-signed certificates."
|
184
|
-
puts " Use --verify-ssl if you want to enable SSL verification."
|
225
|
+
puts "WARNING: SSL verification is disabled by default. iDRAC typically uses self-signed certificates.".yellow
|
226
|
+
puts " Use --verify-ssl if you want to enable SSL verification.".yellow
|
185
227
|
puts ""
|
186
228
|
end
|
187
229
|
end
|
@@ -200,18 +242,5 @@ module IDRAC
|
|
200
242
|
end
|
201
243
|
end
|
202
244
|
|
203
|
-
#
|
204
|
-
|
205
|
-
class StandaloneCLI < Thor
|
206
|
-
# Register the catalog command
|
207
|
-
desc "catalog", "Download Dell firmware catalog"
|
208
|
-
subcommand "catalog", CatalogCommand
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
# Check if the first argument is 'catalog'
|
213
|
-
if ARGV[0] == 'catalog'
|
214
|
-
IDRAC::StandaloneCLI.start(ARGV)
|
215
|
-
else
|
216
|
-
IDRAC::CLI.start(ARGV)
|
217
|
-
end
|
245
|
+
# Start the CLI
|
246
|
+
IDRAC::CLI.start(ARGV)
|
@@ -0,0 +1 @@
|
|
1
|
+
"8e46be845f83db1:0"
|
Binary file
|
data/idrac-0.1.6/.rspec
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
# IDRAC
|
2
|
+
|
3
|
+
A Ruby client for the Dell iDRAC API. This gem provides a command-line interface and a Ruby API for interacting with Dell iDRAC servers.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
- Take screenshots of the iDRAC console
|
8
|
+
- Update firmware using Dell's catalog
|
9
|
+
- Check for firmware updates
|
10
|
+
- Interactive firmware update process
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'idrac'
|
18
|
+
```
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle install
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install idrac
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
### Command Line Interface
|
31
|
+
|
32
|
+
The gem provides a command-line interface for interacting with iDRAC servers:
|
33
|
+
|
34
|
+
```bash
|
35
|
+
# Take a screenshot of the iDRAC console
|
36
|
+
idrac screenshot --host=192.168.1.100 --username=root --password=calvin
|
37
|
+
# Specify a custom output filename
|
38
|
+
idrac screenshot --host=192.168.1.100 --username=root --password=calvin --output=my_screenshot.png
|
39
|
+
|
40
|
+
# Download the Dell firmware catalog
|
41
|
+
idrac firmware:catalog --host=192.168.1.100 --username=root --password=calvin
|
42
|
+
|
43
|
+
# Check firmware status and available updates
|
44
|
+
idrac firmware:status --host=192.168.1.100 --username=root --password=calvin
|
45
|
+
|
46
|
+
# Update firmware using a specific file
|
47
|
+
idrac firmware:update /path/to/firmware.exe --host=192.168.1.100 --username=root --password=calvin
|
48
|
+
|
49
|
+
# Interactive firmware update
|
50
|
+
idrac firmware:interactive --host=192.168.1.100 --username=root --password=calvin
|
51
|
+
```
|
52
|
+
|
53
|
+
### Ruby API
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
require 'idrac'
|
57
|
+
|
58
|
+
# Create a client
|
59
|
+
client = IDRAC.new(
|
60
|
+
host: '192.168.1.100',
|
61
|
+
username: 'root',
|
62
|
+
password: 'calvin'
|
63
|
+
)
|
64
|
+
|
65
|
+
# Take a screenshot (using the client convenience method)
|
66
|
+
filename = client.screenshot
|
67
|
+
puts "Screenshot saved to: #{filename}"
|
68
|
+
|
69
|
+
# Or use the Screenshot class directly for more control
|
70
|
+
screenshot = IDRAC::Screenshot.new(client)
|
71
|
+
filename = screenshot.capture
|
72
|
+
puts "Screenshot saved to: #{filename}"
|
73
|
+
|
74
|
+
# Firmware operations
|
75
|
+
firmware = IDRAC::Firmware.new(client)
|
76
|
+
|
77
|
+
# Download catalog
|
78
|
+
catalog_path = firmware.download_catalog
|
79
|
+
|
80
|
+
# Get system inventory
|
81
|
+
inventory = firmware.get_system_inventory
|
82
|
+
puts "Service Tag: #{inventory[:system][:service_tag]}"
|
83
|
+
|
84
|
+
# Check for updates
|
85
|
+
updates = firmware.check_updates(catalog_path)
|
86
|
+
updates.each do |update|
|
87
|
+
puts "#{update[:name]}: #{update[:current_version]} -> #{update[:available_version]}"
|
88
|
+
end
|
89
|
+
|
90
|
+
# Update firmware
|
91
|
+
job_id = firmware.update('/path/to/firmware.exe', wait: true)
|
92
|
+
puts "Update completed with job ID: #{job_id}"
|
93
|
+
```
|
94
|
+
|
95
|
+
## Development
|
96
|
+
|
97
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
98
|
+
|
99
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
100
|
+
|
101
|
+
## Contributing
|
102
|
+
|
103
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/usiegj00/idrac.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rspec/core/rake_task"
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
7
|
+
|
8
|
+
task default: :spec
|
9
|
+
|
10
|
+
# Add a task that tags and pushes to the repository and builds
|
11
|
+
# the gem and pushes it to rubygems.org.
|
12
|
+
# Depend on the build task to ensure the gem is up to date.
|
13
|
+
task :release => [:build] do
|
14
|
+
system "git tag v#{Idrac::VERSION}"
|
15
|
+
system "git push --tags"
|
16
|
+
system "gem push pkg/idrac-#{Idrac::VERSION}.gem"
|
17
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "idrac"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
require "irb"
|
11
|
+
IRB.start(__FILE__)
|
@@ -0,0 +1,179 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Attempt to load bundler/setup, but don't fail if it's not available
|
4
|
+
begin
|
5
|
+
require "bundler/setup"
|
6
|
+
rescue LoadError
|
7
|
+
# Continue without bundler
|
8
|
+
end
|
9
|
+
|
10
|
+
# Load required gems directly
|
11
|
+
require "thor"
|
12
|
+
require "idrac"
|
13
|
+
|
14
|
+
module IDRAC
|
15
|
+
class CLI < Thor
|
16
|
+
class_option :host, type: :string, required: true, desc: "iDRAC host address"
|
17
|
+
class_option :username, type: :string, required: true, desc: "iDRAC username"
|
18
|
+
class_option :password, type: :string, required: true, desc: "iDRAC password"
|
19
|
+
class_option :port, type: :numeric, default: 443, desc: "iDRAC port"
|
20
|
+
class_option :no_ssl, type: :boolean, default: false, desc: "Disable SSL"
|
21
|
+
class_option :no_verify_ssl, type: :boolean, default: false, desc: "Disable SSL verification"
|
22
|
+
|
23
|
+
desc "firmware:update PATH", "Update firmware using the specified file"
|
24
|
+
method_option :wait, type: :boolean, default: true, desc: "Wait for the update to complete"
|
25
|
+
method_option :timeout, type: :numeric, default: 3600, desc: "Timeout in seconds when waiting"
|
26
|
+
def firmware_update(path)
|
27
|
+
client = create_client
|
28
|
+
firmware = IDRAC::Firmware.new(client)
|
29
|
+
|
30
|
+
begin
|
31
|
+
job_id = firmware.update(path, wait: options[:wait], timeout: options[:timeout])
|
32
|
+
puts "Firmware update initiated with job ID: #{job_id}"
|
33
|
+
rescue IDRAC::Error => e
|
34
|
+
puts "Error: #{e.message}"
|
35
|
+
exit 1
|
36
|
+
ensure
|
37
|
+
client.logout
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "firmware:catalog [DIRECTORY]", "Download Dell firmware catalog"
|
42
|
+
def firmware_catalog(directory = nil)
|
43
|
+
client = create_client
|
44
|
+
firmware = IDRAC::Firmware.new(client)
|
45
|
+
|
46
|
+
begin
|
47
|
+
catalog_path = firmware.download_catalog(directory)
|
48
|
+
puts "Catalog downloaded to: #{catalog_path}"
|
49
|
+
rescue IDRAC::Error => e
|
50
|
+
puts "Error: #{e.message}"
|
51
|
+
exit 1
|
52
|
+
ensure
|
53
|
+
client.logout
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "firmware:status", "Show current firmware status and available updates"
|
58
|
+
method_option :catalog, type: :string, desc: "Path to existing catalog file"
|
59
|
+
def firmware_status
|
60
|
+
client = create_client
|
61
|
+
firmware = IDRAC::Firmware.new(client)
|
62
|
+
|
63
|
+
begin
|
64
|
+
# Get system inventory
|
65
|
+
inventory = firmware.get_system_inventory
|
66
|
+
|
67
|
+
puts "System Information:"
|
68
|
+
puts " Model: #{inventory[:system][:model]}"
|
69
|
+
puts " Manufacturer: #{inventory[:system][:manufacturer]}"
|
70
|
+
puts " Service Tag: #{inventory[:system][:service_tag]}"
|
71
|
+
puts " BIOS Version: #{inventory[:system][:bios_version]}"
|
72
|
+
|
73
|
+
puts "\nInstalled Firmware:"
|
74
|
+
inventory[:firmware].each do |fw|
|
75
|
+
puts " #{fw[:name]}: #{fw[:version]} (#{fw[:updateable] ? 'Updateable' : 'Not Updateable'})"
|
76
|
+
end
|
77
|
+
|
78
|
+
# Check for updates if catalog is available
|
79
|
+
if options[:catalog] || File.exist?(File.join(Dir.pwd, "Catalog.xml"))
|
80
|
+
catalog_path = options[:catalog] || File.join(Dir.pwd, "Catalog.xml")
|
81
|
+
puts "\nChecking for updates using catalog: #{catalog_path}"
|
82
|
+
|
83
|
+
updates = firmware.check_updates(catalog_path)
|
84
|
+
|
85
|
+
if updates.empty?
|
86
|
+
puts "No updates available."
|
87
|
+
else
|
88
|
+
puts "\nAvailable Updates:"
|
89
|
+
updates.each do |update|
|
90
|
+
puts " #{update[:name]}: #{update[:current_version]} -> #{update[:available_version]}"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
else
|
94
|
+
puts "\nTo check for updates, download the catalog first with 'idrac firmware:catalog'"
|
95
|
+
end
|
96
|
+
rescue IDRAC::Error => e
|
97
|
+
puts "Error: #{e.message}"
|
98
|
+
exit 1
|
99
|
+
ensure
|
100
|
+
client.logout
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
desc "firmware:interactive", "Interactive firmware update"
|
105
|
+
method_option :catalog, type: :string, desc: "Path to existing catalog file"
|
106
|
+
def firmware_interactive
|
107
|
+
client = create_client
|
108
|
+
firmware = IDRAC::Firmware.new(client)
|
109
|
+
|
110
|
+
begin
|
111
|
+
catalog_path = options[:catalog]
|
112
|
+
|
113
|
+
# If no catalog specified, check if one exists in current directory
|
114
|
+
if catalog_path.nil? && File.exist?(File.join(Dir.pwd, "Catalog.xml"))
|
115
|
+
catalog_path = File.join(Dir.pwd, "Catalog.xml")
|
116
|
+
end
|
117
|
+
|
118
|
+
# If still no catalog, download it
|
119
|
+
if catalog_path.nil?
|
120
|
+
puts "No catalog found. Downloading..."
|
121
|
+
catalog_path = firmware.download_catalog
|
122
|
+
end
|
123
|
+
|
124
|
+
firmware.interactive_update(catalog_path)
|
125
|
+
rescue IDRAC::Error => e
|
126
|
+
puts "Error: #{e.message}"
|
127
|
+
exit 1
|
128
|
+
ensure
|
129
|
+
client.logout
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
desc "screenshot", "Take a screenshot of the current iDRAC console"
|
134
|
+
method_option :output, type: :string, desc: "Output filename (default: idrac_screenshot_timestamp.png)"
|
135
|
+
def screenshot
|
136
|
+
client = create_client
|
137
|
+
|
138
|
+
begin
|
139
|
+
# Create a Screenshot instance directly
|
140
|
+
screenshot = IDRAC::Screenshot.new(client)
|
141
|
+
filename = screenshot.capture
|
142
|
+
|
143
|
+
# Rename the file if output option is provided
|
144
|
+
if options[:output]
|
145
|
+
new_filename = options[:output]
|
146
|
+
File.rename(filename, new_filename)
|
147
|
+
filename = new_filename
|
148
|
+
end
|
149
|
+
|
150
|
+
puts "Screenshot saved to: #{filename}"
|
151
|
+
rescue IDRAC::Error => e
|
152
|
+
puts "Error: #{e.message}"
|
153
|
+
exit 1
|
154
|
+
ensure
|
155
|
+
client.logout
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
map "firmware:update" => :firmware_update
|
160
|
+
map "firmware:catalog" => :firmware_catalog
|
161
|
+
map "firmware:status" => :firmware_status
|
162
|
+
map "firmware:interactive" => :firmware_interactive
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
def create_client
|
167
|
+
IDRAC::Client.new(
|
168
|
+
host: options[:host],
|
169
|
+
username: options[:username],
|
170
|
+
password: options[:password],
|
171
|
+
port: options[:port],
|
172
|
+
use_ssl: !options[:no_ssl],
|
173
|
+
verify_ssl: !options[:no_verify_ssl]
|
174
|
+
)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
IDRAC::CLI.start(ARGV)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/idrac/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "idrac"
|
7
|
+
spec.version = IDRAC::VERSION
|
8
|
+
spec.authors = ["Jonathan Siegel"]
|
9
|
+
spec.email = ["<248302+usiegj00@users.noreply.github.com>"]
|
10
|
+
|
11
|
+
spec.summary = "API Client for Dell iDRAC"
|
12
|
+
spec.description = "A Ruby client for the Dell iDRAC API"
|
13
|
+
spec.homepage = "http://github.com"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = ">= 3.2.0" # Updated to support Ruby 3.2.x
|
16
|
+
|
17
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
18
|
+
|
19
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
20
|
+
# spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
21
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
22
|
+
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
+
spec.files = Dir.chdir(__dir__) do
|
26
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
27
|
+
(File.expand_path(f) == __FILE__) ||
|
28
|
+
f.start_with?(*%w[test/ spec/ features/ .git .circleci appveyor Gemfile])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
spec.bindir = "bin"
|
32
|
+
spec.executables = ["idrac"]
|
33
|
+
spec.require_paths = ["lib"]
|
34
|
+
|
35
|
+
# Dependencies - Using more flexible version constraints
|
36
|
+
spec.add_dependency "httparty", ">= 0.21.0", "< 0.22.0"
|
37
|
+
spec.add_dependency "nokogiri", ">= 1.15.0", "< 1.19.0"
|
38
|
+
spec.add_dependency "faraday", ">= 2.7.0", "< 2.8.0"
|
39
|
+
spec.add_dependency "faraday-multipart", ">= 1.0.0", "< 1.1.0"
|
40
|
+
spec.add_dependency "thor", ">= 1.2.0", "< 1.4.0"
|
41
|
+
spec.add_dependency "base64", "~> 0.1", ">= 0.1.0"
|
42
|
+
|
43
|
+
# Development dependencies
|
44
|
+
spec.add_development_dependency "bundler", "~> 2.4", ">= 2.4.0"
|
45
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
46
|
+
spec.add_development_dependency "rspec", "~> 3.12"
|
47
|
+
spec.add_development_dependency "debug", "~> 1.8"
|
48
|
+
|
49
|
+
# For more information and examples about making a new gem, check out our
|
50
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
51
|
+
end
|