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,169 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module OneviewSDK
|
5
|
+
# Enclosure resource implementation
|
6
|
+
class Enclosure < Resource
|
7
|
+
BASE_URI = '/rest/enclosures'.freeze
|
8
|
+
|
9
|
+
def initialize(client, params = {}, api_ver = nil)
|
10
|
+
super
|
11
|
+
# Default values:
|
12
|
+
@data['type'] ||= 'EnclosureV200'
|
13
|
+
end
|
14
|
+
|
15
|
+
# @!group Validates
|
16
|
+
|
17
|
+
VALID_LICENSING_INTENTS = %w(NotApplicable OneView OneViewNoiLO OneViewStandard).freeze
|
18
|
+
def validate_licensingIntent(value)
|
19
|
+
fail 'Invalid licensingIntent' unless VALID_LICENSING_INTENTS.include?(value) || value.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
VALID_REFRESH_STATES = %w(NotRefreshing RefreshFailed RefreshPending Refreshing).freeze
|
23
|
+
def validate_refreshState(value)
|
24
|
+
fail 'Invalid refreshState' unless VALID_REFRESH_STATES.include?(value)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @!endgroup
|
28
|
+
|
29
|
+
# Claim/configure the enclosure and its components to the appliance
|
30
|
+
def create
|
31
|
+
ensure_client
|
32
|
+
required_attributes = %w(enclosureGroupUri hostname username password licensingIntent)
|
33
|
+
required_attributes.each { |k| fail "Missing required attribute: '#{k}'" unless @data.key?(k) }
|
34
|
+
|
35
|
+
optional_attrs = %w(enclosureUri firmwareBaselineUri force forceInstallFirmware state unmanagedEnclosure updateFirmwareOn)
|
36
|
+
temp_data = @data.select { |k, _v| required_attributes.include?(k) || optional_attrs.include?(k) }
|
37
|
+
response = @client.rest_post(self.class::BASE_URI, { 'body' => temp_data }, @api_version)
|
38
|
+
new_data = @client.response_handler(response)
|
39
|
+
old_name = @data.select { |k, _v| %w(name rackName).include?(k) } # Save name (if given)
|
40
|
+
%w(username password hostname).each { |k| @data.delete(k) } # These are no longer needed
|
41
|
+
set_all(new_data)
|
42
|
+
set_all(old_name)
|
43
|
+
update
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
# Override update operation because only the name and rackName can be updated (& it uses PATCH).
|
48
|
+
def update(attributes = {})
|
49
|
+
set_all(attributes)
|
50
|
+
ensure_client && ensure_uri
|
51
|
+
cur_state = self.class.find_by(@client, uri: @data['uri']).first
|
52
|
+
unless cur_state[:name] == @data['name']
|
53
|
+
temp_data = [{ op: 'replace', path: '/name', value: @data['name'] }]
|
54
|
+
response = @client.rest_patch(@data['uri'], { 'body' => temp_data }, @api_version)
|
55
|
+
@client.response_handler(response)
|
56
|
+
end
|
57
|
+
unless cur_state[:rackName] == @data['rackName']
|
58
|
+
temp_data = [{ op: 'replace', path: '/rackName', value: @data['rackName'] }]
|
59
|
+
response = @client.rest_patch(@data['uri'], { 'body' => temp_data }, @api_version)
|
60
|
+
@client.response_handler(response)
|
61
|
+
end
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
# Reapply enclosure configuration
|
66
|
+
def configuration
|
67
|
+
ensure_client && ensure_uri
|
68
|
+
response = @client.rest_put(@data['uri'] + '/configuration', {}, @api_version)
|
69
|
+
new_data = @client.response_handler(response)
|
70
|
+
set_all(new_data)
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
# Refresh enclosure along with all of its components
|
75
|
+
# @param [String] state NotRefreshing, RefreshFailed, RefreshPending, Refreshing
|
76
|
+
# @param [Hash] options Optional force fields for refreshing the enclosure
|
77
|
+
def set_refresh_state(state, options = {})
|
78
|
+
ensure_client && ensure_uri
|
79
|
+
s = state.to_s rescue state
|
80
|
+
validate_refreshState(s) # Validate refreshState
|
81
|
+
requestBody = {
|
82
|
+
'body' => {
|
83
|
+
refreshState: s,
|
84
|
+
refreshForceOptions: options
|
85
|
+
}
|
86
|
+
}
|
87
|
+
response = @client.rest_put(@data['uri'] + '/refreshState', requestBody, @api_version)
|
88
|
+
new_data = @client.response_handler(response)
|
89
|
+
set_all(new_data)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Get enclosure script content
|
93
|
+
# @return [String] Script content
|
94
|
+
def script
|
95
|
+
ensure_client && ensure_uri
|
96
|
+
response = @client.rest_get(@data['uri'] + '/script', @api_version)
|
97
|
+
@client.response_handler(response)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Get settings that describe the environmental configuration
|
101
|
+
def environmental_configuration
|
102
|
+
ensure_client && ensure_uri
|
103
|
+
response = @client.rest_get(@data['uri'] + '/environmentalConfiguration', @api_version)
|
104
|
+
@client.response_handler(response)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Retrieves historical utilization
|
108
|
+
# @param [Hash] queryParameters query parameters (ie :startDate, :endDate, :fields, :view, etc.)
|
109
|
+
# @option queryParameters [Array] :fields
|
110
|
+
# @option queryParameters [Time, Date, String] :startDate
|
111
|
+
# @option queryParameters [Time, Date, String] :endDate
|
112
|
+
def utilization(queryParameters = {})
|
113
|
+
ensure_client && ensure_uri
|
114
|
+
uri = "#{@data['uri']}/utilization?"
|
115
|
+
|
116
|
+
queryParameters[:endDate] = convert_time(queryParameters[:endDate])
|
117
|
+
queryParameters[:startDate] = convert_time(queryParameters[:startDate])
|
118
|
+
|
119
|
+
queryParameters.each do |key, value|
|
120
|
+
next if value.nil?
|
121
|
+
uri += case key.to_sym
|
122
|
+
when :fields
|
123
|
+
"fields=#{value.join(',')}"
|
124
|
+
when :startDate, :endDate
|
125
|
+
"filter=#{key}=#{value}"
|
126
|
+
else
|
127
|
+
"#{key}=#{value}"
|
128
|
+
end
|
129
|
+
uri += '&'
|
130
|
+
end
|
131
|
+
uri.chop! # Get rid of trailing '&' or '?'
|
132
|
+
response = @client.rest_get(uri, @api_version)
|
133
|
+
@client.response_handler(response)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Update specific attributes of a given enclosure resource
|
137
|
+
# @param [String] operation operation to be performed
|
138
|
+
# @param [String] path path
|
139
|
+
# @param [String] value value
|
140
|
+
def update_attribute(operation, path, value)
|
141
|
+
ensure_client && ensure_uri
|
142
|
+
response = @client.rest_patch(@data['uri'], { 'body' => [{ op: operation, path: path, value: value }] }, @api_version)
|
143
|
+
@client.response_handler(response)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Associates one Enclosure Group to the enclosure to be added
|
147
|
+
# @param [OneviewSDK<Resource>] eg Enclosure Group associated
|
148
|
+
def set_enclosure_group(eg)
|
149
|
+
eg.retrieve! unless eg['uri']
|
150
|
+
@data['enclosureGroupUri'] = eg['uri']
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
# Convert Date, Time, or String objects to iso8601 string
|
157
|
+
def convert_time(t)
|
158
|
+
case t
|
159
|
+
when nil then nil
|
160
|
+
when Date then t.to_time.utc.iso8601(3)
|
161
|
+
when Time then t.utc.iso8601(3)
|
162
|
+
when String then Time.parse(t).utc.iso8601(3)
|
163
|
+
else fail "Invalid time format '#{t.class}'. Valid options are Time, Date, or String"
|
164
|
+
end
|
165
|
+
rescue StandardError => e
|
166
|
+
raise "Failed to parse time value '#{t}'. #{e.message}"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module OneviewSDK
|
2
|
+
# Enclosure group resource implementation
|
3
|
+
class EnclosureGroup < Resource
|
4
|
+
BASE_URI = '/rest/enclosure-groups'.freeze
|
5
|
+
|
6
|
+
def initialize(client, params = {}, api_ver = nil)
|
7
|
+
super
|
8
|
+
# Default values:
|
9
|
+
@data['type'] ||= 'EnclosureGroupV200'
|
10
|
+
@data['interconnectBayMappingCount'] ||= 8
|
11
|
+
create_interconnect_bay_mapping unless @data['interconnectBayMappings']
|
12
|
+
end
|
13
|
+
|
14
|
+
# @!group Validates
|
15
|
+
|
16
|
+
VALID_INTERCONNECT_BAY_MAPPING_COUNTS = (1..8).freeze
|
17
|
+
def validate_interconnectBayMappingCount(value)
|
18
|
+
fail 'Interconnect Bay Mapping Count out of range 1..8' unless VALID_INTERCONNECT_BAY_MAPPING_COUNTS.include?(value)
|
19
|
+
end
|
20
|
+
|
21
|
+
VALID_IP_ADDRESSING_MODES = %w(DHCP External IpPool).freeze
|
22
|
+
def validate_ipAddressingMode(value)
|
23
|
+
return if !@data['enclosureTypeUri'] || /c7000/ =~ @data['enclosureTypeUri']
|
24
|
+
is_not_a_c7000_without_ip_addressing_mode = !(/c7000/ =~ @data['enclosureTypeUri']) && !value
|
25
|
+
fail "Invalid ip AddressingMode: #{value}" if !VALID_IP_ADDRESSING_MODES.include?(value) || is_not_a_c7000_without_ip_addressing_mode
|
26
|
+
end
|
27
|
+
|
28
|
+
VALID_PORT_MAPPING_COUNTS = (0..8).freeze
|
29
|
+
def validate_portMappingCount(value)
|
30
|
+
fail 'Port Mapping Count out of range 0..8' unless VALID_PORT_MAPPING_COUNTS.include?(value)
|
31
|
+
end
|
32
|
+
|
33
|
+
VALID_POWER_MODES = ['RedundantPowerFeed', 'RedundantPowerSupply', nil].freeze
|
34
|
+
def validate_powerMode(value)
|
35
|
+
fail 'Invalid powerMode' unless VALID_POWER_MODES.include?(value)
|
36
|
+
end
|
37
|
+
|
38
|
+
VALID_STACKING_MODES = %w(Enclosure MultiEnclosure None SwitchPairs).freeze
|
39
|
+
def validate_stackingMode(value)
|
40
|
+
fail 'Invalid stackingMode' unless VALID_STACKING_MODES.include?(value)
|
41
|
+
end
|
42
|
+
|
43
|
+
# @!endgroup
|
44
|
+
|
45
|
+
# Get the script executed by enclosures in this enclosure group
|
46
|
+
# @return [String] script for this enclosure group
|
47
|
+
def get_script
|
48
|
+
ensure_client && ensure_uri
|
49
|
+
response = @client.rest_get(@data['uri'] + '/script', @api_version)
|
50
|
+
@client.response_handler(response)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Change the script executed by enclosures in this enclosure group
|
54
|
+
# @param [String] body script to be executed
|
55
|
+
# @return true if set successfully
|
56
|
+
def set_script(body)
|
57
|
+
ensure_client && ensure_uri
|
58
|
+
response = @client.rest_put(@data['uri'] + '/script', { 'body' => body }, @api_version)
|
59
|
+
@client.response_handler(response)
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
# Add logical interconnect group
|
64
|
+
# @param [OneviewSDK::LogicalInterconnectGroup] lig Logical Interconnect Group
|
65
|
+
def add_logical_interconnect_group(lig)
|
66
|
+
lig.retrieve! unless lig['uri']
|
67
|
+
lig['interconnectMapTemplate']['interconnectMapEntryTemplates'].each do |entry|
|
68
|
+
entry['logicalLocation']['locationEntries'].each do |location|
|
69
|
+
add_lig_to_bay(location['relativeValue'], lig) if location['type'] == 'Bay' && entry['permittedInterconnectTypeUri']
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Create interconnect bay mapping
|
75
|
+
def create_interconnect_bay_mapping
|
76
|
+
@data['interconnectBayMappings'] = []
|
77
|
+
1.upto(@data['interconnectBayMappingCount']) do |bay_number|
|
78
|
+
entry = {
|
79
|
+
'interconnectBay' => bay_number,
|
80
|
+
'logicalInterconnectGroupUri' => nil
|
81
|
+
}
|
82
|
+
@data['interconnectBayMappings'] << entry
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# Add logical interconnect group to bay
|
89
|
+
# @param [Integer] bay Bay number
|
90
|
+
# @param [OneviewSDK::LogicalInterconnectGroup] lig Logical Interconnect Group
|
91
|
+
def add_lig_to_bay(bay, lig)
|
92
|
+
@data['interconnectBayMappings'].each do |location|
|
93
|
+
return location['logicalInterconnectGroupUri'] = lig['uri'] if location['interconnectBay'] == bay
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module OneviewSDK
|
2
|
+
# Ethernet network resource implementation
|
3
|
+
class EthernetNetwork < Resource
|
4
|
+
BASE_URI = '/rest/ethernet-networks'.freeze
|
5
|
+
|
6
|
+
def initialize(client, params = {}, api_ver = nil)
|
7
|
+
super
|
8
|
+
# Default values:
|
9
|
+
@data['ethernetNetworkType'] ||= 'Tagged'
|
10
|
+
@data['type'] ||= 'ethernet-networkV3'
|
11
|
+
end
|
12
|
+
|
13
|
+
# @!group Validates
|
14
|
+
|
15
|
+
VALID_ETHERNET_NETWORK_TYPES = %w(NotApplicable Tagged Tunnel Unknown Untagged).freeze
|
16
|
+
# Validate ethernetNetworkType
|
17
|
+
# @param [String] value Notapplicable, Tagged, Tunnel, Unknown, Untagged
|
18
|
+
def validate_ethernetNetworkType(value)
|
19
|
+
fail 'Invalid network type' unless VALID_ETHERNET_NETWORK_TYPES.include?(value)
|
20
|
+
end
|
21
|
+
|
22
|
+
VALID_PURPOSES = %w(FaultTolerance General Management VMMigration).freeze
|
23
|
+
# Validate purpose
|
24
|
+
# @param [String] value FaultTolerance, General, Management, VMMigration
|
25
|
+
def validate_purpose(value)
|
26
|
+
fail 'Invalid ethernet purpose' unless VALID_PURPOSES.include?(value)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @!endgroup
|
30
|
+
|
31
|
+
# Bulk create ethernet networks
|
32
|
+
# @param [Client] client client to connect with OneView
|
33
|
+
# @param [Hash] options information necessary to create networks
|
34
|
+
# @return [Array] list of ethernet networks created
|
35
|
+
def self.bulk_create(client, options)
|
36
|
+
range = options[:vlanIdRange].split('-').map(&:to_i)
|
37
|
+
options[:type] = 'bulk-ethernet-network'
|
38
|
+
response = client.rest_post(BASE_URI + '/bulk', { 'body' => options }, client.api_version)
|
39
|
+
client.response_handler(response)
|
40
|
+
network_names = []
|
41
|
+
range[0].upto(range[1]) { |i| network_names << "#{options[:namePrefix]}_#{i}" }
|
42
|
+
OneviewSDK::EthernetNetwork.get_all(client).select { |network| network_names.include?(network['name']) }
|
43
|
+
end
|
44
|
+
|
45
|
+
# Get associatedProfiles
|
46
|
+
def get_associated_profiles
|
47
|
+
ensure_client && ensure_uri
|
48
|
+
response = @client.rest_get("#{@data['uri']}/associatedProfiles", @api_version)
|
49
|
+
response.body
|
50
|
+
end
|
51
|
+
|
52
|
+
# Get associatedUplinkGroups
|
53
|
+
def get_associated_uplink_groups
|
54
|
+
ensure_client && ensure_uri
|
55
|
+
response = @client.rest_get("#{@data['uri']}/associatedUplinkGroups", @api_version)
|
56
|
+
response.body
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module OneviewSDK
|
2
|
+
# FC network resource implementation
|
3
|
+
class FCNetwork < Resource
|
4
|
+
BASE_URI = '/rest/fc-networks'.freeze
|
5
|
+
|
6
|
+
def initialize(client, params = {}, api_ver = nil)
|
7
|
+
super
|
8
|
+
# Default values
|
9
|
+
@data['autoLoginRedistribution'] ||= false
|
10
|
+
@data['type'] ||= 'fc-networkV2'
|
11
|
+
@data['linkStabilityTime'] ||= 30
|
12
|
+
@data['fabricType'] ||= 'FabricAttach'
|
13
|
+
end
|
14
|
+
|
15
|
+
# @!group Validates
|
16
|
+
|
17
|
+
VALID_FABRIC_TYPES = %w(DirectAttach FabricAttach).freeze
|
18
|
+
def validate_fabricType(value)
|
19
|
+
fail 'Invalid fabric type' unless VALID_FABRIC_TYPES.include?(value)
|
20
|
+
end
|
21
|
+
|
22
|
+
VALID_LINK_STABILITY_TIMES = (1..1800).freeze
|
23
|
+
def validate_linkStabilityTime(value)
|
24
|
+
return unless @data['fabricType'] && @data['fabricType'] == 'FabricAttach'
|
25
|
+
fail 'Link stability time out of range 1..1800' unless VALID_LINK_STABILITY_TIMES.include?(value)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @!endgroup
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module OneviewSDK
|
2
|
+
# FCoE network resource implementation
|
3
|
+
class FCoENetwork < Resource
|
4
|
+
BASE_URI = '/rest/fcoe-networks'.freeze
|
5
|
+
|
6
|
+
def initialize(client, params = {}, api_ver = nil)
|
7
|
+
super
|
8
|
+
# Default values:
|
9
|
+
@data['connectionTemplateUri'] ||= nil
|
10
|
+
@data['type'] ||= 'fcoe-network'
|
11
|
+
end
|
12
|
+
|
13
|
+
# @!group Validates
|
14
|
+
|
15
|
+
VALID_VLAN_IDS = (1..4094).freeze
|
16
|
+
# Validate vlanId
|
17
|
+
# @param [Fixnum] value 1..4094
|
18
|
+
def validate_vlanId(value)
|
19
|
+
fail 'vlanId out of range 1..4094' unless VALID_VLAN_IDS.include?(value)
|
20
|
+
end
|
21
|
+
|
22
|
+
# @!endgroup
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module OneviewSDK
|
2
|
+
# Firmware bundle resource implementation
|
3
|
+
class FirmwareBundle
|
4
|
+
BASE_URI = '/rest/firmware-bundles'.freeze
|
5
|
+
BOUNDARY = '---OneView-SDK-RubyFormBoundaryWzS4H31b7UMbKMCx'.freeze
|
6
|
+
|
7
|
+
# Upload a firmware bundle file
|
8
|
+
# @param [OneviewSDK::Client] client
|
9
|
+
# @param [String] file_path
|
10
|
+
# @return [OneviewSDK::FirmwareDriver] if the upload was sucessful, return a FirmwareDriver object
|
11
|
+
def self.upload(client, file_path)
|
12
|
+
fail "ERROR: File '#{file_path}' not found!" unless File.file?(file_path)
|
13
|
+
type = case File.extname(file_path)
|
14
|
+
when '.zip' then 'application/x-zip-compressed'
|
15
|
+
when '.exe' then 'application/x-msdownload'
|
16
|
+
else 'application/octet-stream'
|
17
|
+
end
|
18
|
+
|
19
|
+
body = "--#{BOUNDARY}\r\n"
|
20
|
+
body << "Content-Disposition: form-data; name=\"file\"; filename=\"#{File.basename(file_path)}\"\r\n"
|
21
|
+
body << "Content-Type: #{type}\r\n\r\n"
|
22
|
+
body << File.read(file_path)
|
23
|
+
body << "\r\n--#{BOUNDARY}--"
|
24
|
+
|
25
|
+
options = {
|
26
|
+
'Content-Type' => "multipart/form-data; boundary=#{BOUNDARY}",
|
27
|
+
'uploadfilename' => File.basename(file_path),
|
28
|
+
'body' => body
|
29
|
+
}
|
30
|
+
|
31
|
+
response = client.rest_post(BASE_URI, options)
|
32
|
+
data = client.response_handler(response)
|
33
|
+
OneviewSDK::FirmwareDriver.new(client, data)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module OneviewSDK
|
2
|
+
# Firmware driver resource implementation
|
3
|
+
class FirmwareDriver < Resource
|
4
|
+
BASE_URI = '/rest/firmware-drivers'.freeze
|
5
|
+
|
6
|
+
def initialize(client, params = {}, api_ver = nil)
|
7
|
+
super
|
8
|
+
# Default values
|
9
|
+
@data['type'] ||= 'firmware-baselines'
|
10
|
+
end
|
11
|
+
|
12
|
+
def create
|
13
|
+
fail 'Method not available for this resource!'
|
14
|
+
end
|
15
|
+
|
16
|
+
def update
|
17
|
+
create
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|