redfish_tools 0.2.5 → 0.2.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 4c6ab90b8f72271602995c5d80f2db1c5a98464932e0f63998b12be0e62f056b
4
- data.tar.gz: 4e855bde6379285944b597b86a985e6b14ff7accb841f7cbc499a355ade3b88f
2
+ SHA1:
3
+ metadata.gz: d8e4fd83aeaa6c8af2e97fce4d2e92802cc97281
4
+ data.tar.gz: d2e92b0b838758132ba345a45ab6d8c4b423dcf3
5
5
  SHA512:
6
- metadata.gz: c0bb889e806d7d7512308122084d7c376caffd163dc931418829d3f512c73423e9c1bbd79392b65e28c70ab984e2f0bf1d0114869558755a40d59c8231f2b31f
7
- data.tar.gz: e6e7f0d9331526ef9c0237bae96ee5ce27c94ad77150179c6913f6fe2449b9ccf59a75d8d47472db0477496cdf1a0f735a73f14f51d847de6f6c14e607059bbe
6
+ metadata.gz: f8c3805f96c543a24c787edb52ec70a60ccf097b547e9a6ca87909219f810f091852479ba4237439c2ae146222536f9a30fdc2f814fd3b4491c1d9296ebbf184
7
+ data.tar.gz: f02fc22a3b4600a5b41621026bf26c98160f6c72665d23290b6df19dd538f209a267fca3ebfd2ece864e76e7840d16dc08f3a9013b5418631726a1bbfd678aa4
@@ -1,4 +1,3 @@
1
- sudo: false
2
1
  language: ruby
3
2
  cache: bundler
4
3
  rvm:
@@ -27,5 +27,26 @@ module RedfishTools
27
27
  @basic_auth_header ||= "Basic " +
28
28
  Base64.strict_encode64("#{username}:#{password}")
29
29
  end
30
+
31
+ def system_actions
32
+ # Hash of action_id => system_id
33
+ @system_actions ||= load_all_system_actions
34
+ end
35
+
36
+ private
37
+
38
+ def load_all_system_actions
39
+ systems_id = datastore.get("/redfish/v1").body["Systems"]["@odata.id"]
40
+ datastore.get(systems_id).body["Members"].reduce({}) do |acc, link|
41
+ acc.merge(load_system_actions(link["@odata.id"]))
42
+ end
43
+ end
44
+
45
+ def load_system_actions(id)
46
+ actions = datastore.get(id).body.dig("Actions") || {}
47
+ actions.each_with_object({}) do |(name, data), acc|
48
+ acc[data["target"]] = { name: name, system_id: id }
49
+ end
50
+ end
30
51
  end
31
52
  end
@@ -12,21 +12,38 @@ module RedfishTools
12
12
 
13
13
  def_delegators :@server,
14
14
  :datastore, :login_path, :username, :password,
15
- :basic_auth_header
15
+ :basic_auth_header, :system_actions
16
16
 
17
17
  BAD_HEADERS = Set.new(["connection", "content-length", "keep-alive"])
18
18
  DEFAULT_HEADERS = {
19
19
  "content-type" => "application/json"
20
20
  }.freeze
21
+ TRANSITIONS = {
22
+ "On" => {
23
+ "GracefullShutdown" => "Off",
24
+ "ForceOff" => "Off",
25
+ "PushPowerButton" => "Off",
26
+ "Nmi" => "Off",
27
+ "GracefullRestart" => "On",
28
+ "ForceRestart" => "On",
29
+ "PowerCycle" => "On",
30
+ }.freeze,
31
+ "Off" => {
32
+ "On" => "On",
33
+ "ForceOn" => "On",
34
+ "PushPowerButton" => "On",
35
+ }.freeze,
36
+ }.freeze
21
37
 
22
38
  def service(request, response)
23
39
  return response.status = 401 unless authorized?(request)
24
- return response.status = 404 unless datastore.get(request.path).body
25
40
 
26
41
  super
27
42
  end
28
43
 
29
44
  def do_GET(request, response)
45
+ return response.status = 404 unless datastore.get(request.path).body
46
+
30
47
  item = datastore.get(request.path)
31
48
  response.status = 200
32
49
  set_headers(response, item.headers)
@@ -34,18 +51,27 @@ module RedfishTools
34
51
  end
35
52
 
36
53
  def do_POST(request, response)
54
+ action = system_actions[request.path]
37
55
  item = datastore.get(request.path)
38
- return response.status = 405 unless item.body["Members"]
56
+ return response.status = 404 unless action || item.body
57
+ return response.status = 405 if action.nil? && item.body["Members"].nil?
39
58
 
40
59
  data = JSON.parse(request.body)
41
- item_n = login_path?(request) ? login(item, data) : new_item(item, data)
42
- return response.status = 400 unless item_n&.body
60
+ if action
61
+ body, headers, status = execute_action(action, data)
62
+ elsif login_path?(request.path)
63
+ body, headers, status = login(item, data)
64
+ else
65
+ body, headers, status = new_item(item, data)
66
+ end
43
67
 
44
- response.status = 201
45
- set_headers(response, item_n.headers)
46
- response.body = item_n.body.to_json
68
+ response.status = status
69
+ set_headers(response, headers)
70
+ response.body = body.to_json
47
71
  rescue JSON::ParserError
48
72
  response.status = 400
73
+ set_headers(response)
74
+ response.body = error_body("Invalid JSON").to_json
49
75
  end
50
76
 
51
77
  def do_PUT(_request, response)
@@ -57,27 +83,54 @@ module RedfishTools
57
83
  end
58
84
 
59
85
  def do_DELETE(request, response)
60
- delete_item(datastore.get(request.path))
86
+ item = datastore.get(request.path)
87
+ return response.status = 404 unless item.body
88
+
89
+ delete_item(item)
61
90
  response.status = 204
62
91
  end
63
92
 
64
93
  private
65
94
 
66
- def login_path?(request)
67
- login_path == request.path.chomp("/")
95
+ def error_body(msg)
96
+ { "error" => { "message" => msg } }
97
+ end
98
+
99
+ def execute_action(action, data)
100
+ # TODO(@tadeboro): This method currently only handles reset action.
101
+ system = datastore.get(action[:system_id]).body
102
+ action = system["Actions"][action[:name]]
103
+ reset = data["ResetType"]
104
+
105
+ unless action["ResetType@Redfish.AllowableValues"].include?(reset)
106
+ return error_body("Invalid reset type"), nill, 400
107
+ end
108
+
109
+ unless TRANSITIONS[system["PowerState"]].key?(reset)
110
+ return error_body("Invalid reset type for curent state"), nil, 400
111
+ end
112
+
113
+ # Simulate reset action
114
+ system["PowerState"] = TRANSITIONS[system["PowerState"]][reset]
115
+
116
+ [error_body("Success"), nil, 200]
117
+ end
118
+
119
+ def login_path?(path)
120
+ login_path == path.chomp("/")
68
121
  end
69
122
 
70
123
  def login(item, data)
71
124
  user = data["UserName"]
72
- pass = data["Password"]
73
- return nil unless username == user && password == pass
125
+ unless username == user && password == data["Password"]
126
+ return error_body("Invalid username/password"), nil, 400
127
+ end
74
128
 
75
- res = new_item(item,
76
- "@odata.type" => "#Session.v1_1_0.Session",
77
- "UserName" => user,
78
- "Password" => nil)
79
- res.headers = DEFAULT_HEADERS.merge("X-Auth-Token" => res.body["Id"])
80
- res
129
+ body, _, status = new_item(item,
130
+ "@odata.type" => "#Session.v1_1_0.Session",
131
+ "UserName" => user,
132
+ "Password" => nil)
133
+ [body, DEFAULT_HEADERS.merge("X-Auth-Token" => body["Id"]), status]
81
134
  end
82
135
 
83
136
  def new_item(item, data)
@@ -87,7 +140,8 @@ module RedfishTools
87
140
  item.body["Members"].push("@odata.id" => oid)
88
141
 
89
142
  base = { "@odata.id" => oid, "Id" => id, "Name" => id }
90
- datastore.set(oid, base.merge(data), parent: item)
143
+ new_item = datastore.set(oid, base.merge(data), parent: item)
144
+ [new_item.body, nil, 201]
91
145
  end
92
146
 
93
147
  def delete_item(item)
@@ -105,7 +159,7 @@ module RedfishTools
105
159
  always_allow?(request.path) || # Non-protected endpoints
106
160
  authorized_basic?(request) ||
107
161
  authorized_session?(request) ||
108
- (request.request_method == "POST" && login_path?(request))
162
+ (request.request_method == "POST" && login_path?(request.path))
109
163
  end
110
164
 
111
165
  def always_allow?(path)
@@ -134,7 +188,7 @@ module RedfishTools
134
188
  nil
135
189
  end
136
190
 
137
- def set_headers(response, headers)
191
+ def set_headers(response, headers = nil)
138
192
  headers ||= DEFAULT_HEADERS
139
193
  headers.each do |k, v|
140
194
  response[k] = v unless BAD_HEADERS.member?(k.downcase)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RedfishTools
4
- VERSION = "0.2.5"
4
+ VERSION = "0.2.6"
5
5
  end
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_runtime_dependency "server_sent_events", "~> 0.1.1"
33
33
  spec.add_runtime_dependency "thor", "~> 0.19"
34
34
 
35
- spec.add_development_dependency "bundler", "~> 1.16"
35
+ spec.add_development_dependency "bundler"
36
36
  spec.add_development_dependency "pry"
37
37
  spec.add_development_dependency "rake", "~> 10.0"
38
38
  spec.add_development_dependency "rspec", "~> 3.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redfish_tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tadej Borovšak
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-09-24 00:00:00.000000000 Z
11
+ date: 2019-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redfish_client
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '1.16'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '1.16'
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: pry
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -176,7 +176,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
176
176
  version: '0'
177
177
  requirements: []
178
178
  rubyforge_project:
179
- rubygems_version: 2.7.7
179
+ rubygems_version: 2.6.14
180
180
  signing_key:
181
181
  specification_version: 4
182
182
  summary: Collection of tools for working with Redfish services.