oneview-sdk 1.0.0
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 +7 -0
- data/.gitattributes +2 -0
- data/.gitignore +29 -0
- data/.rubocop.yml +73 -0
- data/.travis.yml +8 -0
- data/CHANGELOG.md +39 -0
- data/Gemfile +2 -0
- data/LICENSE +201 -0
- data/README.md +317 -0
- data/Rakefile +90 -0
- data/bin/oneview-sdk-ruby +4 -0
- data/lib/oneview-sdk.rb +9 -0
- data/lib/oneview-sdk/cli.rb +407 -0
- data/lib/oneview-sdk/client.rb +163 -0
- data/lib/oneview-sdk/config_loader.rb +20 -0
- data/lib/oneview-sdk/resource.rb +313 -0
- data/lib/oneview-sdk/resource/enclosure.rb +169 -0
- data/lib/oneview-sdk/resource/enclosure_group.rb +98 -0
- data/lib/oneview-sdk/resource/ethernet_network.rb +60 -0
- data/lib/oneview-sdk/resource/fc_network.rb +31 -0
- data/lib/oneview-sdk/resource/fcoe_network.rb +25 -0
- data/lib/oneview-sdk/resource/firmware_bundle.rb +37 -0
- data/lib/oneview-sdk/resource/firmware_driver.rb +21 -0
- data/lib/oneview-sdk/resource/interconnect.rb +87 -0
- data/lib/oneview-sdk/resource/lig_uplink_set.rb +86 -0
- data/lib/oneview-sdk/resource/logical_enclosure.rb +84 -0
- data/lib/oneview-sdk/resource/logical_interconnect.rb +283 -0
- data/lib/oneview-sdk/resource/logical_interconnect_group.rb +92 -0
- data/lib/oneview-sdk/resource/server_hardware.rb +88 -0
- data/lib/oneview-sdk/resource/server_hardware_type.rb +27 -0
- data/lib/oneview-sdk/resource/server_profile.rb +37 -0
- data/lib/oneview-sdk/resource/server_profile_template.rb +24 -0
- data/lib/oneview-sdk/resource/storage_pool.rb +41 -0
- data/lib/oneview-sdk/resource/storage_system.rb +63 -0
- data/lib/oneview-sdk/resource/uplink_set.rb +119 -0
- data/lib/oneview-sdk/resource/volume.rb +188 -0
- data/lib/oneview-sdk/resource/volume_snapshot.rb +27 -0
- data/lib/oneview-sdk/resource/volume_template.rb +106 -0
- data/lib/oneview-sdk/rest.rb +163 -0
- data/lib/oneview-sdk/ssl_helper.rb +75 -0
- data/lib/oneview-sdk/version.rb +4 -0
- data/oneview-sdk.gemspec +31 -0
- metadata +204 -0
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require_relative 'config_loader'
|
3
|
+
require_relative 'rest'
|
4
|
+
require_relative 'ssl_helper'
|
5
|
+
|
6
|
+
module OneviewSDK
|
7
|
+
# The client defines the connection to the OneView server and handles communication with it.
|
8
|
+
class Client
|
9
|
+
DEFAULT_API_VERSION = 200
|
10
|
+
|
11
|
+
attr_reader :url, :user, :token, :password, :max_api_version
|
12
|
+
attr_accessor :ssl_enabled, :api_version, :logger, :log_level, :cert_store, :print_wait_dots
|
13
|
+
|
14
|
+
include Rest
|
15
|
+
|
16
|
+
# Create client object, establish connection, and set up logging and api version.
|
17
|
+
# @param [Hash] options the options to configure the client
|
18
|
+
# @option options [Logger] :logger (Logger.new(STDOUT)) Logger object to use.
|
19
|
+
# Must implement debug(String), info(String), warn(String), error(String), & level=
|
20
|
+
# @option options [Symbol] :log_level (:info) Log level. Logger must define a constant with this name. ie Logger::INFO
|
21
|
+
# @option options [Boolean] :print_wait_dots (false) When true, prints status dots while waiting on tasks to complete.
|
22
|
+
# @option options [String] :url URL of OneView appliance
|
23
|
+
# @option options [String] :user ('Administrator') Username to use for authentication with OneView appliance
|
24
|
+
# @option options [String] :password (ENV['ONEVIEWSDK_PASSWORD']) Password to use for authentication with OneView appliance
|
25
|
+
# @option options [String] :token (ENV['ONEVIEWSDK_TOKEN']) Token to use for authentication with OneView appliance
|
26
|
+
# Use this OR the username and password (not both). Token has precedence.
|
27
|
+
# @option options [Integer] :api_version (200) API Version to use by default for requests
|
28
|
+
# @option options [Boolean] :ssl_enabled (true) Use ssl for requests? Respects ENV['ONEVIEWSDK_SSL_ENABLED']
|
29
|
+
def initialize(options = {})
|
30
|
+
options = Hash[options.map { |k, v| [k.to_sym, v] }] # Convert string hash keys to symbols
|
31
|
+
@logger = options[:logger] || Logger.new(STDOUT)
|
32
|
+
[:debug, :info, :warn, :error, :level=].each { |m| fail "Logger must respond to #{m} method " unless @logger.respond_to?(m) }
|
33
|
+
@log_level = options[:log_level] || :info
|
34
|
+
@logger.level = @logger.class.const_get(@log_level.upcase) rescue @log_level
|
35
|
+
@print_wait_dots = options.fetch(:print_wait_dots, false)
|
36
|
+
@url = options[:url] || ENV['ONEVIEWSDK_URL']
|
37
|
+
fail 'Must set the url option' unless @url
|
38
|
+
@max_api_version = appliance_api_version
|
39
|
+
if options[:api_version] && options[:api_version].to_i > @max_api_version
|
40
|
+
logger.warn "API version #{options[:api_version]} is greater than the appliance API version (#{@max_api_version})"
|
41
|
+
end
|
42
|
+
@api_version = options[:api_version] || [DEFAULT_API_VERSION, @max_api_version].min
|
43
|
+
@ssl_enabled = true
|
44
|
+
if ENV.key?('ONEVIEWSDK_SSL_ENABLED')
|
45
|
+
if %w(true false 1 0).include?(ENV['ONEVIEWSDK_SSL_ENABLED'])
|
46
|
+
@ssl_enabled = ! %w(false 0).include?(ENV['ONEVIEWSDK_SSL_ENABLED'])
|
47
|
+
else
|
48
|
+
@logger.warn "Unrecognized ssl_enabled value '#{ENV['ONEVIEWSDK_SSL_ENABLED']}'. Valid options are 'true' & 'false'"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
@ssl_enabled = options[:ssl_enabled] unless options[:ssl_enabled].nil?
|
52
|
+
@cert_store = OneviewSDK::SSLHelper.load_trusted_certs if @ssl_enabled
|
53
|
+
@token = options[:token] || ENV['ONEVIEWSDK_TOKEN']
|
54
|
+
return if @token
|
55
|
+
@logger.warn 'User option not set. Using default (Administrator)' unless options[:user] || ENV['ONEVIEWSDK_USER']
|
56
|
+
@user = options[:user] || ENV['ONEVIEWSDK_USER'] || 'Administrator'
|
57
|
+
@password = options[:password] || ENV['ONEVIEWSDK_PASSWORD']
|
58
|
+
fail 'Must set user & password options or token option' unless @password
|
59
|
+
@token = login
|
60
|
+
end
|
61
|
+
|
62
|
+
# Tell OneView to create the resource using the current attribute data
|
63
|
+
# @param [Resource] resource the object to create
|
64
|
+
def create(resource)
|
65
|
+
resource.client = self
|
66
|
+
resource.create
|
67
|
+
end
|
68
|
+
|
69
|
+
# Set attribute data and save to OneView
|
70
|
+
# @param [Resource] resource the object to update
|
71
|
+
def update(resource, attributes = {})
|
72
|
+
resource.client = self
|
73
|
+
resource.update(attributes)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Updates this object using the data that exists on OneView
|
77
|
+
# @param [Resource] resource the object to refresh
|
78
|
+
def refresh(resource)
|
79
|
+
resource.client = self
|
80
|
+
resource.refresh
|
81
|
+
end
|
82
|
+
|
83
|
+
# Deletes this object from OneView
|
84
|
+
# @param [Resource] resource the object to delete
|
85
|
+
def delete(resource)
|
86
|
+
resource.client = self
|
87
|
+
resource.delete
|
88
|
+
end
|
89
|
+
|
90
|
+
# Get array of all resources of a specified type
|
91
|
+
# @param [String] type Resource type
|
92
|
+
# @return [Array<Resource>] Results
|
93
|
+
# @example Get all Ethernet Networks
|
94
|
+
# networks = @client.get_all('EthernetNetworks')
|
95
|
+
def get_all(type)
|
96
|
+
OneviewSDK.resource_named(type).get_all(self)
|
97
|
+
rescue StandardError
|
98
|
+
raise "Invalid resource type '#{type}'"
|
99
|
+
end
|
100
|
+
|
101
|
+
# Wait for a task to complete
|
102
|
+
# @param [String] task_uri
|
103
|
+
# @raise [RuntimeError] if the task resulted in an error or early termination.
|
104
|
+
# @return [Hash] if the task completed sucessfully, return the task details
|
105
|
+
def wait_for(task_uri)
|
106
|
+
fail 'Must specify a task_uri!' if task_uri.nil? || task_uri.empty?
|
107
|
+
loop do
|
108
|
+
task_uri.gsub!(%r{/https:(.*)\/rest/}, '/rest')
|
109
|
+
task = rest_get(task_uri)
|
110
|
+
body = JSON.parse(task.body)
|
111
|
+
case body['taskState'].downcase
|
112
|
+
when 'completed'
|
113
|
+
return body
|
114
|
+
when 'warning'
|
115
|
+
@logger.warn "Task ended with warning status. Details: #{JSON.pretty_generate(body['taskErrors']) rescue body}"
|
116
|
+
return body
|
117
|
+
when 'error', 'killed', 'terminated'
|
118
|
+
msg = "Task ended with bad state: '#{body['taskState']}'.\nResponse: "
|
119
|
+
msg += body['taskErrors'] ? JSON.pretty_generate(body['taskErrors']) : JSON.pretty_generate(body)
|
120
|
+
fail(msg)
|
121
|
+
else
|
122
|
+
print '.' if @print_wait_dots
|
123
|
+
sleep 10
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
# Get current api version from the OneView appliance
|
132
|
+
def appliance_api_version
|
133
|
+
options = { 'Content-Type' => :none, 'X-API-Version' => :none, 'auth' => :none }
|
134
|
+
response = rest_api(:get, '/rest/version', options)
|
135
|
+
version = response_handler(response)['currentVersion']
|
136
|
+
fail "Couldn't get API version" unless version
|
137
|
+
version = version.to_i if version.class != Fixnum
|
138
|
+
version
|
139
|
+
rescue
|
140
|
+
@logger.warn "Failed to get OneView max api version. Using default (#{DEFAULT_API_VERSION})"
|
141
|
+
DEFAULT_API_VERSION
|
142
|
+
end
|
143
|
+
|
144
|
+
# Log in to OneView appliance and set max_api_version
|
145
|
+
def login(retries = 2)
|
146
|
+
options = {
|
147
|
+
'body' => {
|
148
|
+
'userName' => @user,
|
149
|
+
'password' => @password,
|
150
|
+
'authLoginDomain' => 'LOCAL'
|
151
|
+
}
|
152
|
+
}
|
153
|
+
response = rest_post('/rest/login-sessions', options)
|
154
|
+
body = response_handler(response)
|
155
|
+
return body['sessionID'] if body['sessionID']
|
156
|
+
fail "\nERROR! Couldn't log into OneView server at #{@url}. Response: #{response}\n#{response.body}"
|
157
|
+
rescue StandardError => e
|
158
|
+
raise e unless retries > 0
|
159
|
+
@logger.debug 'Failed to log in to OneView. Retrying...'
|
160
|
+
return login(retries - 1)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module OneviewSDK
|
5
|
+
# Configuration helper class to allow .yaml & .json files to be easily used to specify OneView Configuration
|
6
|
+
class Config
|
7
|
+
|
8
|
+
# Load config from .yaml or .json file
|
9
|
+
# @param [String] path The full path to the configuration file
|
10
|
+
# @return [Hash] hash of the configuration
|
11
|
+
def self.load(path)
|
12
|
+
path = File.join(Dir.pwd, path) unless Pathname.new(path).absolute?
|
13
|
+
expanded_path = File.expand_path(path)
|
14
|
+
JSON.parse(IO.read(expanded_path))
|
15
|
+
rescue
|
16
|
+
data = YAML.load_file(expanded_path)
|
17
|
+
Hash[data.map { |k, v| [k.to_s, v] }]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,313 @@
|
|
1
|
+
require_relative 'client'
|
2
|
+
|
3
|
+
# OneviewSDK Resources
|
4
|
+
module OneviewSDK
|
5
|
+
# Resource base class that defines all common resource functionality.
|
6
|
+
class Resource
|
7
|
+
BASE_URI = '/rest'.freeze
|
8
|
+
|
9
|
+
attr_accessor \
|
10
|
+
:client,
|
11
|
+
:data,
|
12
|
+
:api_version,
|
13
|
+
:logger
|
14
|
+
|
15
|
+
# Create a resource object, associate it with a client, and set its properties.
|
16
|
+
# @param [Client] client The Client object with a connection to the OneView appliance
|
17
|
+
# @param [Hash] params The options for this resource (key-value pairs)
|
18
|
+
# @param [Integer] api_ver The api version to use when interracting with this resource.
|
19
|
+
# Defaults to client.api_version if exists, or OneviewSDK::Client::DEFAULT_API_VERSION.
|
20
|
+
def initialize(client, params = {}, api_ver = nil)
|
21
|
+
fail 'Must specify a valid client' unless client.is_a?(OneviewSDK::Client)
|
22
|
+
@client = client
|
23
|
+
@logger = @client.logger
|
24
|
+
@api_version = api_ver || @client.api_version
|
25
|
+
if @api_version > @client.max_api_version
|
26
|
+
fail "#{self.class.name} api_version '#{@api_version}' is greater than the client's max_api_version '#{@client.max_api_version}'"
|
27
|
+
end
|
28
|
+
@data ||= {}
|
29
|
+
set_all(params)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Retrieve resource details based on this resource's name or URI.
|
33
|
+
# @note Name or URI must be specified inside resource
|
34
|
+
# @return [Boolean] Whether or not retrieve was successful
|
35
|
+
def retrieve!
|
36
|
+
fail 'Must set resource name or uri before trying to retrieve!' unless @data['name'] || @data['uri']
|
37
|
+
results = self.class.find_by(@client, name: @data['name']) if @data['name']
|
38
|
+
results = self.class.find_by(@client, uri: @data['uri']) if @data['uri'] && (!results || results.empty?)
|
39
|
+
return false unless results.size == 1
|
40
|
+
set_all(results[0].data)
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
# Check if a resource exists
|
45
|
+
# @note name or uri must be specified inside resource
|
46
|
+
# @return [Boolean] Whether or not resource exists
|
47
|
+
def exists?
|
48
|
+
fail 'Must set resource name or uri before trying to retrieve!' unless @data['name'] || @data['uri']
|
49
|
+
return true if @data['name'] && self.class.find_by(@client, name: @data['name']).size == 1
|
50
|
+
return true if @data['uri'] && self.class.find_by(@client, uri: @data['uri']).size == 1
|
51
|
+
false
|
52
|
+
end
|
53
|
+
|
54
|
+
# Set the given hash of key-value pairs as resource data attributes
|
55
|
+
# @param [Hash, Resource] params The options for this resource (key-value pairs or Resource object)
|
56
|
+
# @note All top-level keys will be converted to strings
|
57
|
+
# @return [Resource] self
|
58
|
+
def set_all(params = {})
|
59
|
+
params = params.data if params.class <= Resource
|
60
|
+
params = Hash[params.map { |(k, v)| [k.to_s, v] }]
|
61
|
+
params.each { |key, value| set(key.to_s, value) }
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
# Set a resource attribute with the given value and call any validation method if necessary
|
66
|
+
# @param [String] key attribute name
|
67
|
+
# @param value value to assign to the given attribute
|
68
|
+
# @note Keys will be converted to strings
|
69
|
+
def set(key, value)
|
70
|
+
method_name = "validate_#{key}"
|
71
|
+
send(method_name.to_sym, value) if respond_to?(method_name.to_sym)
|
72
|
+
@data[key.to_s] = value
|
73
|
+
end
|
74
|
+
|
75
|
+
# Run block once for each data key-value pair
|
76
|
+
def each(&block)
|
77
|
+
@data.each(&block)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Access data using hash syntax
|
81
|
+
# @param [String, Symbol] key Name of key to get value for
|
82
|
+
# @return The value of the given key. If not found, returns nil
|
83
|
+
# @note The key will be converted to a string
|
84
|
+
def [](key)
|
85
|
+
@data[key.to_s]
|
86
|
+
end
|
87
|
+
|
88
|
+
# Set data using hash syntax
|
89
|
+
# @param [String, Symbol] key Name of key to set the value for
|
90
|
+
# @param [Object] value to set for the given key
|
91
|
+
# @note The key will be converted to a string
|
92
|
+
# @return The value set for the given key
|
93
|
+
def []=(key, value)
|
94
|
+
set(key, value)
|
95
|
+
value
|
96
|
+
end
|
97
|
+
|
98
|
+
# Check equality of 2 resources. Same as eql?(other)
|
99
|
+
# @param [Resource] other The other resource to check equality for
|
100
|
+
# @return [Boolean] Whether or not the two objects are equal
|
101
|
+
def ==(other)
|
102
|
+
self_state = instance_variables.sort.map { |v| instance_variable_get(v) }
|
103
|
+
other_state = other.instance_variables.sort.map { |v| other.instance_variable_get(v) }
|
104
|
+
other.class == self.class && other_state == self_state
|
105
|
+
end
|
106
|
+
|
107
|
+
# Check equality of 2 resources. Same as ==(other)
|
108
|
+
# @param [Resource] other The other resource to check equality for
|
109
|
+
# @return [Boolean] Whether or not the two objects are equal
|
110
|
+
def eql?(other)
|
111
|
+
self == other
|
112
|
+
end
|
113
|
+
|
114
|
+
# Check equality of data on other resource with that of this resource.
|
115
|
+
# @note Doesn't check the client, logger, or api_version if another Resource is passed in
|
116
|
+
# @param [Hash, Resource] other Resource or hash to compare key-value pairs with
|
117
|
+
# @example Compare to hash
|
118
|
+
# myResource = OneviewSDK::Resource.new(client, { name: 'res1', description: 'example'}, 200)
|
119
|
+
# myResource.like?(description: '') # returns false
|
120
|
+
# myResource.like?(name: 'res1') # returns true
|
121
|
+
# @return [Boolean] Whether or not the two objects are alike
|
122
|
+
def like?(other)
|
123
|
+
recursive_like?(other, @data)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Create the resource on OneView using the current data
|
127
|
+
# @note Calls the refresh method to set additional data
|
128
|
+
# @raise [RuntimeError] if the client is not set
|
129
|
+
# @raise [RuntimeError] if the resource creation fails
|
130
|
+
# @return [Resource] self
|
131
|
+
def create
|
132
|
+
ensure_client
|
133
|
+
response = @client.rest_post(self.class::BASE_URI, { 'body' => @data }, @api_version)
|
134
|
+
body = @client.response_handler(response)
|
135
|
+
set_all(body)
|
136
|
+
self
|
137
|
+
end
|
138
|
+
|
139
|
+
# Delete the resource from OneView if it exists, then create it using the current data
|
140
|
+
# @note Calls refresh method to set additional data
|
141
|
+
# @raise [RuntimeError] if the client is not set
|
142
|
+
# @raise [RuntimeError] if the resource creation fails
|
143
|
+
# @return [Resource] self
|
144
|
+
def create!
|
145
|
+
temp = self.class.new(@client, @data)
|
146
|
+
temp.delete if temp.retrieve!
|
147
|
+
create
|
148
|
+
end
|
149
|
+
|
150
|
+
# Updates this object using the data that exists on OneView
|
151
|
+
# @note Will overwrite any data that differs from OneView
|
152
|
+
# @return [Resource] self
|
153
|
+
def refresh
|
154
|
+
ensure_client && ensure_uri
|
155
|
+
response = @client.rest_get(@data['uri'], @api_version)
|
156
|
+
body = @client.response_handler(response)
|
157
|
+
set_all(body)
|
158
|
+
self
|
159
|
+
end
|
160
|
+
|
161
|
+
# Set data and save to OneView
|
162
|
+
# @param [Hash] attributes The attributes to add/change for this resource (key-value pairs)
|
163
|
+
# @raise [RuntimeError] if the client or uri is not set
|
164
|
+
# @raise [RuntimeError] if the resource save fails
|
165
|
+
# @return [Resource] self
|
166
|
+
def update(attributes = {})
|
167
|
+
set_all(attributes)
|
168
|
+
ensure_client && ensure_uri
|
169
|
+
response = @client.rest_put(@data['uri'], { 'body' => @data }, @api_version)
|
170
|
+
@client.response_handler(response)
|
171
|
+
self
|
172
|
+
end
|
173
|
+
|
174
|
+
# Delete resource from OneView
|
175
|
+
# @return [true] if resource was deleted successfully
|
176
|
+
def delete
|
177
|
+
ensure_client && ensure_uri
|
178
|
+
response = @client.rest_delete(@data['uri'], {}, @api_version)
|
179
|
+
@client.response_handler(response)
|
180
|
+
true
|
181
|
+
end
|
182
|
+
|
183
|
+
# Save resource to json or yaml file
|
184
|
+
# @param [String] file_path The full path to the file
|
185
|
+
# @param [Symbol] format The format. Options: [:json, :yml, :yaml]. Defaults to .json
|
186
|
+
# @note If a .yml or .yaml file extension is given in the file_path, the format will be set automatically
|
187
|
+
# @return [True] The Resource was saved successfully
|
188
|
+
def to_file(file_path, format = :json)
|
189
|
+
format = :yml if %w(.yml .yaml).include? File.extname(file_path)
|
190
|
+
temp_data = { type: self.class.name, api_version: @api_version, data: @data }
|
191
|
+
case format.to_sym
|
192
|
+
when :json
|
193
|
+
File.open(file_path, 'w') { |f| f.write(JSON.pretty_generate(temp_data)) }
|
194
|
+
when :yml, :yaml
|
195
|
+
File.open(file_path, 'w') { |f| f.write(temp_data.to_yaml) }
|
196
|
+
else
|
197
|
+
fail "Invalid format: #{format}"
|
198
|
+
end
|
199
|
+
true
|
200
|
+
end
|
201
|
+
|
202
|
+
# Get resource schema
|
203
|
+
# @note This may not be implemented in the API for every resource. Check the API docs
|
204
|
+
# @return [Hash] Schema
|
205
|
+
def schema
|
206
|
+
self.class.schema(@client)
|
207
|
+
end
|
208
|
+
|
209
|
+
# Get resource schema
|
210
|
+
# @param [Client] client
|
211
|
+
# @return [Hash] Schema
|
212
|
+
def self.schema(client)
|
213
|
+
response = client.rest_get("#{self::BASE_URI}/schema", client.api_version)
|
214
|
+
client.response_handler(response)
|
215
|
+
rescue StandardError => e
|
216
|
+
client.logger.error('This resource does not implement the schema endpoint!') if e.message =~ /404 NOT FOUND/
|
217
|
+
raise e
|
218
|
+
end
|
219
|
+
|
220
|
+
# Load resource from a .json or .yaml file
|
221
|
+
# @param [Client] client The client object to associate this resource with
|
222
|
+
# @param [String] file_path The full path to the file
|
223
|
+
# @return [Resource] New resource created from the file contents
|
224
|
+
def self.from_file(client, file_path)
|
225
|
+
resource = OneviewSDK::Config.load(file_path)
|
226
|
+
new(client, resource['data'], resource['api_version'])
|
227
|
+
end
|
228
|
+
|
229
|
+
# Make a GET request to the resource uri and return an array with results matching the search
|
230
|
+
# @param [Client] client
|
231
|
+
# @param [Hash] attributes Hash containing the attributes name and value
|
232
|
+
# @param [String] uri URI of the endpoint
|
233
|
+
# @return [Array<Resource>] Results matching the search
|
234
|
+
def self.find_by(client, attributes, uri = self::BASE_URI)
|
235
|
+
results = []
|
236
|
+
loop do
|
237
|
+
response = client.rest_get(uri)
|
238
|
+
body = client.response_handler(response)
|
239
|
+
members = body['members']
|
240
|
+
break unless members
|
241
|
+
members.each do |member|
|
242
|
+
temp = new(client, member)
|
243
|
+
results.push(temp) if temp.like?(attributes)
|
244
|
+
end
|
245
|
+
break unless body['nextPageUri']
|
246
|
+
uri = body['nextPageUri']
|
247
|
+
end
|
248
|
+
results
|
249
|
+
end
|
250
|
+
|
251
|
+
# Make a GET request to the resource base uri and return an array with all objects of this type
|
252
|
+
# @return [Array<Resource>] Results
|
253
|
+
def self.get_all(client)
|
254
|
+
find_by(client, {})
|
255
|
+
end
|
256
|
+
|
257
|
+
protected
|
258
|
+
|
259
|
+
# Fail unless @client is set for this resource.
|
260
|
+
def ensure_client
|
261
|
+
fail 'Please set client attribute before interacting with this resource' unless @client
|
262
|
+
true
|
263
|
+
end
|
264
|
+
|
265
|
+
# Fail unless @data['uri'] is set for this resource.
|
266
|
+
def ensure_uri
|
267
|
+
fail 'Please set uri attribute before interacting with this resource' unless @data['uri']
|
268
|
+
true
|
269
|
+
end
|
270
|
+
|
271
|
+
# Fail for methods that are not available for one resource
|
272
|
+
def unavailable_method
|
273
|
+
fail "The method ##{caller[0][/`.*'/][1..-2]} is unavailable for this resource"
|
274
|
+
end
|
275
|
+
|
276
|
+
private
|
277
|
+
|
278
|
+
# Recursive helper method for like?
|
279
|
+
# Allows comparison of nested hash structures
|
280
|
+
def recursive_like?(other, data = @data)
|
281
|
+
fail "Can't compare with object type: #{other.class}! Must respond_to :each" unless other.respond_to?(:each)
|
282
|
+
other.each do |key, val|
|
283
|
+
return false unless data && data.respond_to?(:[])
|
284
|
+
if val.is_a?(Hash)
|
285
|
+
return false unless data.class == Hash && recursive_like?(val, data[key.to_s])
|
286
|
+
elsif val != data[key.to_s]
|
287
|
+
return false
|
288
|
+
end
|
289
|
+
end
|
290
|
+
true
|
291
|
+
end
|
292
|
+
|
293
|
+
end
|
294
|
+
|
295
|
+
# Get resource class that matches the type given
|
296
|
+
# @param [String] type Name of the desired class type
|
297
|
+
# @return [Class] Resource class or nil if not found
|
298
|
+
def self.resource_named(type)
|
299
|
+
classes = {}
|
300
|
+
orig_classes = []
|
301
|
+
ObjectSpace.each_object(Class).select { |klass| klass < OneviewSDK::Resource }.each do |c|
|
302
|
+
name = c.name.split('::').last
|
303
|
+
orig_classes.push(name)
|
304
|
+
classes[name.downcase.delete('_').delete('-')] = c
|
305
|
+
classes["#{name.downcase.delete('_').delete('-')}s"] = c
|
306
|
+
end
|
307
|
+
new_type = type.to_s.downcase.gsub(/[ -_]/, '')
|
308
|
+
return classes[new_type] if classes.keys.include?(new_type)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
# Load all resources:
|
313
|
+
Dir[File.dirname(__FILE__) + '/resource/*.rb'].each { |file| require file }
|