redfish_tools 0.2.5 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
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.