idrac 0.1.31 → 0.1.38

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.
data/idrac-0.1.6/Rakefile DELETED
@@ -1,17 +0,0 @@
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
@@ -1,11 +0,0 @@
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__)
@@ -1,179 +0,0 @@
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)
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
@@ -1,51 +0,0 @@
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
@@ -1,109 +0,0 @@
1
- require 'faraday'
2
- require 'faraday/multipart'
3
- require 'nokogiri'
4
- require 'base64'
5
- require 'uri'
6
- require 'httparty'
7
-
8
- module IDRAC
9
- class Client
10
- attr_reader :host, :username, :password, :port, :use_ssl, :verify_ssl
11
-
12
- def initialize(host:, username:, password:, port: 443, use_ssl: true, verify_ssl: true)
13
- @host = host
14
- @username = username
15
- @password = password
16
- @port = port
17
- @use_ssl = use_ssl
18
- @verify_ssl = verify_ssl
19
- @session_id = nil
20
- @cookies = nil
21
- end
22
-
23
- def connection
24
- @connection ||= Faraday.new(url: base_url, ssl: { verify: verify_ssl }) do |faraday|
25
- faraday.request :multipart
26
- faraday.request :url_encoded
27
- faraday.adapter Faraday.default_adapter
28
- end
29
- end
30
-
31
- def login
32
- response = connection.post('/data/login') do |req|
33
- req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
34
- req.body = "user=#{username}&password=#{password}"
35
- end
36
-
37
- if response.status == 200
38
- # Extract session ID from response
39
- doc = Nokogiri::HTML(response.body)
40
- @session_id = doc.at_css('script:contains("_this.SID")').text.match(/_this\.SID\s*=\s*"([^"]+)"/)[1] rescue nil
41
-
42
- # Store cookies for screenshot functionality
43
- @cookies = response.headers['set-cookie']
44
-
45
- # Extract forward URL for screenshot functionality
46
- xml_doc = Nokogiri::XML(response.body)
47
- error_message = xml_doc.at_xpath('//errorMsg')&.text
48
-
49
- if error_message && !error_message.empty?
50
- raise Error, "Error Message: #{error_message}"
51
- end
52
-
53
- forward_url = xml_doc.xpath('//forwardUrl').text
54
- return forward_url
55
- else
56
- raise Error, "Login failed with status #{response.status}: #{response.body}"
57
- end
58
- end
59
-
60
- def logout
61
- return unless @session_id
62
-
63
- response = connection.get('/data/logout') do |req|
64
- req.headers['Cookie'] = "sessionid=#{@session_id}"
65
- end
66
-
67
- @session_id = nil
68
- @cookies = nil
69
- response.status == 200
70
- end
71
-
72
- def authenticated_request(method, path, options = {})
73
- login unless @session_id
74
-
75
- options[:headers] ||= {}
76
- options[:headers]['Cookie'] = "sessionid=#{@session_id}"
77
-
78
- response = connection.send(method, path, options[:params]) do |req|
79
- req.headers.merge!(options[:headers])
80
- req.body = options[:body] if options[:body]
81
- end
82
-
83
- response
84
- end
85
-
86
- def get(path:, headers: {})
87
- response = HTTParty.get(
88
- "#{base_url}/#{path}",
89
- headers: {
90
- "User-Agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36",
91
- "Accept-Encoding" => "deflate, gzip",
92
- "Cookie" => @cookies
93
- }.merge(headers),
94
- verify: false
95
- )
96
- end
97
-
98
- def screenshot
99
- # Create a Screenshot instance and capture a screenshot
100
- screenshot_instance = Screenshot.new(self)
101
- screenshot_instance.capture
102
- end
103
-
104
- def base_url
105
- protocol = use_ssl ? 'https' : 'http'
106
- "#{protocol}://#{host}:#{port}"
107
- end
108
- end
109
- end