Class: Supermicro::Client
- Inherits:
-
Object
- Object
- Supermicro::Client
- Includes:
- Bios, Boot, Debuggable, Jobs, License, Network, Power, Storage, System, SystemConfig, Tasks, Utility, VirtualMedia
- Defined in:
- lib/supermicro/client.rb
Instance Attribute Summary collapse
-
#direct_mode ⇒ Object
Returns the value of attribute direct_mode.
-
#host ⇒ Object
readonly
Returns the value of attribute host.
-
#host_header ⇒ Object
readonly
Returns the value of attribute host_header.
-
#password ⇒ Object
readonly
Returns the value of attribute password.
-
#port ⇒ Object
readonly
Returns the value of attribute port.
-
#retry_count ⇒ Object
Returns the value of attribute retry_count.
-
#retry_delay ⇒ Object
Returns the value of attribute retry_delay.
-
#session ⇒ Object
readonly
Returns the value of attribute session.
-
#use_ssl ⇒ Object
readonly
Returns the value of attribute use_ssl.
-
#username ⇒ Object
readonly
Returns the value of attribute username.
-
#verbosity ⇒ Object
Returns the value of attribute verbosity.
-
#verify_ssl ⇒ Object
readonly
Returns the value of attribute verify_ssl.
Class Method Summary collapse
Instance Method Summary collapse
- #authenticated_request(method, path, body: nil, headers: {}, timeout: nil, open_timeout: nil, **options) ⇒ Object
- #base_url ⇒ Object
- #connection ⇒ Object
- #get(path:, headers: {}) ⇒ Object
- #get_firmware_version ⇒ Object
- #handle_location(location) ⇒ Object
- #handle_response(response) ⇒ Object
-
#initialize(host:, username:, password:, port: 443, use_ssl: true, verify_ssl: false, direct_mode: false, retry_count: 3, retry_delay: 1, host_header: nil) ⇒ Client
constructor
A new instance of Client.
- #login ⇒ Object
- #logout ⇒ Object
- #redfish_version ⇒ Object
- #wait_for_task(task_id) ⇒ Object
- #with_retries(max_retries = nil, initial_delay = nil, error_classes = nil) ⇒ Object
Methods included from Network
#get_bmc_network, #set_bmc_dhcp, #set_bmc_network
Methods included from Tasks
#poll_task, #wait_for_task_completion
Methods included from SpinnerHelper
Methods included from License
#activate_license, #check_virtual_media_license, #clear_license, #licenses
Methods included from Utility
#accounts, #clear_sel_log, #create_account, #delete_account, #sel_log, #sel_summary, #service_info, #sessions, #update_account_password
Methods included from SystemConfig
#manager_info, #manager_network_protocol, #reset_manager, #set_manager_datetime, #set_network_protocol
Methods included from Bios
#bios_attributes, #bios_error_prompt_disabled?, #bios_hdd_placeholder_enabled?, #bios_os_power_control_enabled?, #ensure_sensible_bios!, #ensure_uefi_boot, #pending_bios_settings, #reset_bios_defaults, #set_bios_attribute, #set_bios_error_prompt, #set_bios_os_power_control
Methods included from Boot
#boot, #boot_config, #boot_options, #boot_raw, #boot_to_bios_setup, #boot_to_cd, #boot_to_disk, #boot_to_pxe, #boot_to_usb, #clear_boot_override, #configure_boot_settings, #get_boot_devices, #set_boot_order, #set_boot_order_hd_first, #set_boot_override, #set_one_time_boot_to_virtual_media
Methods included from VirtualMedia
#eject_virtual_media, #find_best_virtual_media_device, #insert_virtual_media, #mount_iso_and_boot, #test_iso_accessibility, #unmount_all_media, #virtual_media, #virtual_media_status
Methods included from System
#cpus, #fans, #memory, #nics, #power_consumption, #power_consumption_watts, #psus, #system_health, #system_info, #temperatures
Methods included from Storage
#drives, #storage_controllers, #storage_summary, #volumes
Methods included from Jobs
#cancel_job, #clear_jobs!, #job_status, #jobs, #jobs_detail, #jobs_summary, #wait_for_job
Methods included from Debuggable
Methods included from Power
#power_cycle, #power_off, #power_on, #power_restart, #power_status, #reset_type_allowed
Constructor Details
#initialize(host:, username:, password:, port: 443, use_ssl: true, verify_ssl: false, direct_mode: false, retry_count: 3, retry_delay: 1, host_header: nil) ⇒ Client
Returns a new instance of Client.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/supermicro/client.rb', line 31 def initialize(host:, username:, password:, port: 443, use_ssl: true, verify_ssl: false, direct_mode: false, retry_count: 3, retry_delay: 1, host_header: nil) @host = host @username = username @password = password @port = port @use_ssl = use_ssl @verify_ssl = verify_ssl @direct_mode = direct_mode @host_header = host_header @verbosity = 0 @retry_count = retry_count @retry_delay = retry_delay @session = Session.new(self) ObjectSpace.define_finalizer(self, self.class.finalizer(@session)) end |
Instance Attribute Details
#direct_mode ⇒ Object
Returns the value of attribute direct_mode.
15 16 17 |
# File 'lib/supermicro/client.rb', line 15 def direct_mode @direct_mode end |
#host ⇒ Object (readonly)
Returns the value of attribute host.
14 15 16 |
# File 'lib/supermicro/client.rb', line 14 def host @host end |
#host_header ⇒ Object (readonly)
Returns the value of attribute host_header.
14 15 16 |
# File 'lib/supermicro/client.rb', line 14 def host_header @host_header end |
#password ⇒ Object (readonly)
Returns the value of attribute password.
14 15 16 |
# File 'lib/supermicro/client.rb', line 14 def password @password end |
#port ⇒ Object (readonly)
Returns the value of attribute port.
14 15 16 |
# File 'lib/supermicro/client.rb', line 14 def port @port end |
#retry_count ⇒ Object
Returns the value of attribute retry_count.
15 16 17 |
# File 'lib/supermicro/client.rb', line 15 def retry_count @retry_count end |
#retry_delay ⇒ Object
Returns the value of attribute retry_delay.
15 16 17 |
# File 'lib/supermicro/client.rb', line 15 def retry_delay @retry_delay end |
#session ⇒ Object (readonly)
Returns the value of attribute session.
14 15 16 |
# File 'lib/supermicro/client.rb', line 14 def session @session end |
#use_ssl ⇒ Object (readonly)
Returns the value of attribute use_ssl.
14 15 16 |
# File 'lib/supermicro/client.rb', line 14 def use_ssl @use_ssl end |
#username ⇒ Object (readonly)
Returns the value of attribute username.
14 15 16 |
# File 'lib/supermicro/client.rb', line 14 def username @username end |
#verbosity ⇒ Object
Returns the value of attribute verbosity.
15 16 17 |
# File 'lib/supermicro/client.rb', line 15 def verbosity @verbosity end |
#verify_ssl ⇒ Object (readonly)
Returns the value of attribute verify_ssl.
14 15 16 |
# File 'lib/supermicro/client.rb', line 14 def verify_ssl @verify_ssl end |
Class Method Details
.connect(host:, username:, password:, **options) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/supermicro/client.rb', line 58 def self.connect(host:, username:, password:, **) client = new(host: host, username: username, password: password, **) return client unless block_given? begin client.login yield client ensure client.logout end end |
.finalizer(session) ⇒ Object
49 50 51 52 53 54 55 56 |
# File 'lib/supermicro/client.rb', line 49 def self.finalizer(session) proc do begin session.delete if session.x_auth_token rescue end end end |
Instance Method Details
#authenticated_request(method, path, body: nil, headers: {}, timeout: nil, open_timeout: nil, **options) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/supermicro/client.rb', line 106 def authenticated_request(method, path, body: nil, headers: {}, timeout: nil, open_timeout: nil, **) = { body: body, headers: headers, timeout: timeout, open_timeout: open_timeout }.merge().compact with_retries do _perform_authenticated_request(method, path, ) end end |
#base_url ⇒ Object
125 126 127 128 |
# File 'lib/supermicro/client.rb', line 125 def base_url protocol = use_ssl ? 'https' : 'http' "#{protocol}://#{host}:#{port}" end |
#connection ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/supermicro/client.rb', line 70 def connection @connection ||= Faraday.new(url: base_url, ssl: { verify: verify_ssl }) do |faraday| faraday.request :multipart faraday.request :url_encoded faraday.adapter Faraday.default_adapter if @verbosity > 0 faraday.response :logger, Logger.new(STDOUT), bodies: @verbosity >= 2 do |logger| logger.filter(/(Authorization: Basic )([^,\n]+)/, '\1[FILTERED]') logger.filter(/(Password"=>"?)([^,"]+)/, '\1[FILTERED]') end end end end |
#get(path:, headers: {}) ⇒ Object
119 120 121 122 123 |
# File 'lib/supermicro/client.rb', line 119 def get(path:, headers: {}) with_retries do _perform_get(path: path, headers: headers) end end |
#get_firmware_version ⇒ Object
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/supermicro/client.rb', line 140 def get_firmware_version response = authenticated_request(:get, "/redfish/v1/Managers/1?$select=FirmwareVersion") if response.status == 200 begin data = JSON.parse(response.body) return data["FirmwareVersion"] rescue JSON::ParserError raise Error, "Failed to parse firmware version response: #{response.body}" end else response = authenticated_request(:get, "/redfish/v1/Managers/1") if response.status == 200 begin data = JSON.parse(response.body) return data["FirmwareVersion"] rescue JSON::ParserError raise Error, "Failed to parse firmware version response: #{response.body}" end else raise Error, "Failed to get firmware version. Status code: #{response.status}" end end end |
#handle_location(location) ⇒ Object
254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/supermicro/client.rb', line 254 def handle_location(location) return nil if location.nil? || location.empty? id = location.split("/").last if location.include?("/TaskService/Tasks/") wait_for_task(id) else wait_for_job(id) if respond_to?(:wait_for_job) end end |
#handle_response(response) ⇒ Object
242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/supermicro/client.rb', line 242 def handle_response(response) if response.headers["location"] return handle_location(response.headers["location"]) end if response.status.between?(200, 299) return response.body else raise Error, "Failed to #{response.status} - #{response.body}" end end |
#login ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/supermicro/client.rb', line 84 def login if @direct_mode debug "Using direct mode (Basic Auth) for all requests", 1, :light_yellow return true end if session.create debug "Successfully logged in to Supermicro BMC using Redfish session", 1, :green return true else debug "Failed to create Redfish session, falling back to direct mode", 1, :light_yellow @direct_mode = true return true end end |
#logout ⇒ Object
100 101 102 103 104 |
# File 'lib/supermicro/client.rb', line 100 def logout session.delete if session.x_auth_token debug "Logged out from Supermicro BMC", 1, :green return true end |
#redfish_version ⇒ Object
130 131 132 133 134 135 136 137 138 |
# File 'lib/supermicro/client.rb', line 130 def redfish_version response = authenticated_request(:get, "/redfish/v1") if response.status == 200 data = JSON.parse(response.body) data["RedfishVersion"] else raise Error, "Failed to get Redfish version: #{response.status} - #{response.body}" end end |
#wait_for_task(task_id) ⇒ Object
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/supermicro/client.rb', line 188 def wait_for_task(task_id) task = nil begin loop do task_response = authenticated_request(:get, "/redfish/v1/TaskService/Tasks/#{task_id}") case task_response.status when 200..299 task = JSON.parse(task_response.body) if task["TaskState"] != "Running" break end percent_complete = nil if task["Oem"] && task["Oem"]["Supermicro"] && task["Oem"]["Supermicro"]["PercentComplete"] percent_complete = task["Oem"]["Supermicro"]["PercentComplete"] debug "Task progress: #{percent_complete}% complete", 1 end debug "Waiting for task to complete...: #{task["TaskState"]} #{task["TaskStatus"]}", 1 sleep 5 else return { status: :failed, error: "Failed to check task status: #{task_response.status} - #{task_response.body}" } end end if task["TaskState"] == "Completed" && task["TaskStatus"] == "OK" return { status: :success } else debug task.inspect, 1, :yellow = [] if task["Messages"] && task["Messages"].is_a?(Array) = task["Messages"].map { |m| m["Message"] }.compact end return { status: :failed, task_state: task["TaskState"], task_status: task["TaskStatus"], messages: , error: .first || "Task failed with state: #{task["TaskState"]}" } end rescue => e return { status: :error, error: "Exception monitoring task: #{e.}" } end end |
#with_retries(max_retries = nil, initial_delay = nil, error_classes = nil) ⇒ Object
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/supermicro/client.rb', line 166 def with_retries(max_retries = nil, initial_delay = nil, error_classes = nil) max_retries ||= @retry_count initial_delay ||= @retry_delay error_classes ||= [StandardError] retries = 0 begin yield rescue *error_classes => e retries += 1 if retries <= max_retries delay = initial_delay * (retries ** 1.5).to_i debug "RETRY: #{e.} - Attempt #{retries}/#{max_retries}, waiting #{delay}s", 1, :yellow sleep delay retry else debug "MAX RETRIES REACHED: #{e.} after #{max_retries} attempts", 1, :red raise e end end end |