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