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.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +2 -0
  3. data/.gitignore +29 -0
  4. data/.rubocop.yml +73 -0
  5. data/.travis.yml +8 -0
  6. data/CHANGELOG.md +39 -0
  7. data/Gemfile +2 -0
  8. data/LICENSE +201 -0
  9. data/README.md +317 -0
  10. data/Rakefile +90 -0
  11. data/bin/oneview-sdk-ruby +4 -0
  12. data/lib/oneview-sdk.rb +9 -0
  13. data/lib/oneview-sdk/cli.rb +407 -0
  14. data/lib/oneview-sdk/client.rb +163 -0
  15. data/lib/oneview-sdk/config_loader.rb +20 -0
  16. data/lib/oneview-sdk/resource.rb +313 -0
  17. data/lib/oneview-sdk/resource/enclosure.rb +169 -0
  18. data/lib/oneview-sdk/resource/enclosure_group.rb +98 -0
  19. data/lib/oneview-sdk/resource/ethernet_network.rb +60 -0
  20. data/lib/oneview-sdk/resource/fc_network.rb +31 -0
  21. data/lib/oneview-sdk/resource/fcoe_network.rb +25 -0
  22. data/lib/oneview-sdk/resource/firmware_bundle.rb +37 -0
  23. data/lib/oneview-sdk/resource/firmware_driver.rb +21 -0
  24. data/lib/oneview-sdk/resource/interconnect.rb +87 -0
  25. data/lib/oneview-sdk/resource/lig_uplink_set.rb +86 -0
  26. data/lib/oneview-sdk/resource/logical_enclosure.rb +84 -0
  27. data/lib/oneview-sdk/resource/logical_interconnect.rb +283 -0
  28. data/lib/oneview-sdk/resource/logical_interconnect_group.rb +92 -0
  29. data/lib/oneview-sdk/resource/server_hardware.rb +88 -0
  30. data/lib/oneview-sdk/resource/server_hardware_type.rb +27 -0
  31. data/lib/oneview-sdk/resource/server_profile.rb +37 -0
  32. data/lib/oneview-sdk/resource/server_profile_template.rb +24 -0
  33. data/lib/oneview-sdk/resource/storage_pool.rb +41 -0
  34. data/lib/oneview-sdk/resource/storage_system.rb +63 -0
  35. data/lib/oneview-sdk/resource/uplink_set.rb +119 -0
  36. data/lib/oneview-sdk/resource/volume.rb +188 -0
  37. data/lib/oneview-sdk/resource/volume_snapshot.rb +27 -0
  38. data/lib/oneview-sdk/resource/volume_template.rb +106 -0
  39. data/lib/oneview-sdk/rest.rb +163 -0
  40. data/lib/oneview-sdk/ssl_helper.rb +75 -0
  41. data/lib/oneview-sdk/version.rb +4 -0
  42. data/oneview-sdk.gemspec +31 -0
  43. 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