hpe3par_sdk 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,292 @@
1
+ # (c) Copyright 2016-2017 Hewlett Packard Enterprise Development LP
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Unless required by applicable law or agreed to in writing, software distributed
8
+ # under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
9
+ # CONDITIONS OF ANY KIND, either express or implied. See the License for the
10
+ # specific language governing permissions and limitations under the License.
11
+
12
+ require_relative 'util'
13
+ require_relative 'constants'
14
+ require_relative 'exceptions'
15
+ require_relative 'task_manager'
16
+ require_relative 'ssh'
17
+ require_relative 'volume_set_manager'
18
+ require_relative 'models'
19
+
20
+ module Hpe3parSdk
21
+ class VolumeManager
22
+ def initialize(http, ssh, app_type)
23
+ @http = http
24
+ @ssh = ssh
25
+ @task = TaskManager.new(http)
26
+ @volume_set = VolumeSetManager.new(http)
27
+ @app_type = app_type
28
+ end
29
+
30
+ def get_volumes(volume_type)
31
+ volumes = Array[]
32
+ response = @http.get('/volumes')
33
+ response[1]['members'].each do |member|
34
+ volumes.push(VirtualVolume.new(member)) if member['copyType'] == volume_type
35
+ end
36
+ volumes
37
+ end
38
+
39
+ def get_volume(name)
40
+ if name.nil? || name.strip.empty?
41
+ raise 'Volume name cannot be nil or empty'
42
+ else
43
+ VirtualVolume.new(@http.get("/volumes/#{name}")[1])
44
+ end
45
+ end
46
+
47
+ def get_volume_by_wwn(wwn)
48
+ response = @http.get("/volumes?query=\"wwn EQ #{wwn}\"")
49
+ if response[1].key?('members') && !response[1]['members'].empty?
50
+ return VirtualVolume.new(response[1]['members'][0])
51
+ else
52
+ raise HTTPNotFound.new(nil, "Volume with WWN #{wwn} does not exist", nil, 404)
53
+ end
54
+ end
55
+
56
+ def create_volume(name, cpg_name, size_mib, optional = nil)
57
+ info = { 'name' => name,
58
+ 'cpg' => cpg_name,
59
+ 'sizeMiB' => size_mib,
60
+ #Adding information related to telemetry
61
+ 'objectKeyValues' => [
62
+ {
63
+ 'key' => 'type' ,
64
+ 'value' => @app_type
65
+ }
66
+ ]
67
+ }
68
+
69
+ info = Util.merge_hash(info, optional) if optional
70
+ volumes_url = '/volumes'
71
+ @http.post(volumes_url, body: info)
72
+ end
73
+
74
+ def get_volume_snapshot_names(name)
75
+ snapshots = []
76
+ headers, body = @http.get("/volumes?query=\"copyOf EQ #{name}\"")
77
+ for member in body['members']
78
+ snapshots.push(member['name'])
79
+ end
80
+ snapshots
81
+ end
82
+
83
+ def get_volume_snapshots(name)
84
+ response = @http.get("/volumes?query=\"copyOf EQ #{name}\"")
85
+ volume_snapshots = []
86
+ response[1]['members'].each do |snapshot|
87
+ volume_snapshots.push(VirtualVolume.new(snapshot))
88
+ end
89
+ volume_snapshots
90
+ end
91
+
92
+ def delete_volume(name)
93
+ response = @http.delete("/volumes/#{name}")
94
+ response[1]
95
+ end
96
+
97
+ def modify_volume(name, volume_mods)
98
+ @http.put("/volumes/#{name}", body: volume_mods)
99
+ if volume_mods.key? ('newName') && !volume_mods['newName'].nil?
100
+ name = volume_mods['newName']
101
+ end
102
+ setVolumeMetaData(name, 'type', @app_type)
103
+ end
104
+
105
+ def grow_volume(name, amount)
106
+ info = { 'action' => VolumeCustomAction::GROW_VOLUME, 'sizeMiB' => amount }
107
+ response = @http.put("/volumes/#{name}", body: info)
108
+ response[1]
109
+ end
110
+
111
+ def create_physical_copy(src_name, dest_name, dest_cpg, optional = nil)
112
+ parameters = { :destVolume => dest_name, :destCPG => dest_cpg }
113
+ parameters = Util.merge_hash(parameters, optional) if optional
114
+
115
+
116
+ if !parameters.key?(:online) || !((parameters[:online]))
117
+ # 3Par won't allow destCPG to be set if it's not an online copy.
118
+ parameters.delete(:destCPG)
119
+ end
120
+
121
+ info = { :action => 'createPhysicalCopy', :parameters => parameters }
122
+
123
+ response = @http.post("/volumes/#{src_name}", body: info)
124
+ response[1]
125
+ end
126
+
127
+ def stop_offline_physical_copy(volume_name)
128
+ _sync_physical_copy(volume_name, VolumeCustomAction::STOP_PHYSICAL_COPY)
129
+ end
130
+
131
+ def is_online_physical_copy(name)
132
+ task = _find_task(name, active=true)
133
+ if task.nil?
134
+ false
135
+ else
136
+ true
137
+ end
138
+ end
139
+
140
+ def stop_online_physical_copy(name)
141
+ task = _find_task(name, active=false)
142
+ unless task.nil?
143
+ task_id = task[0].split(",")[0]
144
+ unless task_id.nil?
145
+ cmd = ['canceltask', '-f', task_id]
146
+ command = cmd.join(" ")
147
+ result = @ssh.run(command)
148
+ unless result.include? "is not active"
149
+ ready = false
150
+ while ready == false
151
+ sleep(1)
152
+ task = _find_task(name, false)
153
+ if task.nil?
154
+ ready = true
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ def _find_task(name, active=false)
163
+ cmd = ['showtask']
164
+ if active
165
+ cmd.push('-active')
166
+ end
167
+ cmd.push(name)
168
+ command = cmd.join(" ")
169
+
170
+ result = @ssh.run(command).split("\n")
171
+ if result[0].gsub("\n",'') =='No tasks.'
172
+ return nil
173
+ end
174
+ result
175
+ end
176
+
177
+ def resync_physical_copy(volume_name)
178
+ _sync_physical_copy(volume_name, VolumeCustomAction::RESYNC_PHYSICAL_COPY)
179
+ end
180
+
181
+ def _sync_physical_copy(volume_name, action)
182
+ info = { 'action' => action }
183
+ response = @http.put("/volumes/#{volume_name}", body: info)
184
+ response[1]
185
+ end
186
+
187
+ def get_online_physical_copy_status(name)
188
+ status = nil
189
+ tasks = @task.get_all_tasks
190
+ tasks.each do |task|
191
+ status = task['status'] if task['name'] == name &&
192
+ task['type'] == TaskType::ONLINE_COPY
193
+ end
194
+ raise HPE3PARException.new(nil, 'Volume not an online physical copy') if status.nil?
195
+ status
196
+ end
197
+
198
+ def tune_volume(name, tune_operation, optional = nil)
199
+ info = { 'action' => VolumeCustomAction::TUNE_VOLUME,
200
+ 'tuneOperation' => tune_operation }
201
+ info = Util.merge_hash(info, optional) if optional
202
+ response = @http.put("/volumes/#{name}", body: info)
203
+ response[1]
204
+ end
205
+
206
+
207
+
208
+ def create_snapshot(name, copy_of_name, optional = nil)
209
+ parameters = { 'name' => name }
210
+ parameters = Util.merge_hash(parameters, optional) if optional
211
+ info = { 'action' => 'createSnapshot',
212
+ 'parameters' => parameters }
213
+
214
+ response = @http.post("/volumes/#{copy_of_name}", body: info)
215
+ response[1]
216
+ end
217
+
218
+ def restore_snapshot(name, optional = nil)
219
+ info = { 'action' => VolumeCustomAction::PROMOTE_VIRTUAL_COPY }
220
+ info = Util.merge_hash(info, optional) if optional
221
+
222
+ response = @http.put("/volumes/#{name}", body: info)
223
+ response[1]
224
+ end
225
+
226
+ def setVolumeMetaData(name, key, value)
227
+ key_exists = false
228
+ info = {
229
+ 'key' => key,
230
+ 'value' => value
231
+ }
232
+
233
+ begin
234
+ response = @http.post("/volumes/#{name}/objectKeyValues", body: info)
235
+ rescue Hpe3parSdk::HTTPConflict => ex
236
+ key_exists = true
237
+ rescue
238
+ end
239
+
240
+ if key_exists
241
+ info = {
242
+ 'value' => value
243
+ }
244
+ begin
245
+ response = @http.put("/volumes/#{name}/objectKeyValues/#{key}", body: info)
246
+ rescue; end
247
+ end
248
+ end
249
+
250
+ def volume_exists?(name)
251
+ begin
252
+ get_volume(name)
253
+ return true
254
+ rescue Hpe3parSdk::HTTPNotFound => ex
255
+ return false
256
+ end
257
+ end
258
+
259
+ def volume_set_exists?(name)
260
+ begin
261
+ get_volume_set(name)
262
+ return true
263
+ rescue Hpe3parSdk::HTTPNotFound => ex
264
+ return false
265
+ end
266
+ end
267
+
268
+ def online_physical_copy_exists?(src_name, phy_copy_name)
269
+ begin
270
+ if volume_exists?(src_name) and volume_exists?(phy_copy_name) and !_find_task(phy_copy_name,true).nil?
271
+ return true
272
+ else
273
+ return false
274
+ end
275
+ rescue Hpe3parSdk::HTTPNotFound => ex
276
+ return false
277
+ end
278
+ end
279
+
280
+ def offline_physical_copy_exists?(src_name, phy_copy_name)
281
+ begin
282
+ if volume_exists?(src_name) and volume_exists?(phy_copy_name) and !_find_task(src_name + "->" + phy_copy_name,true).nil?
283
+ return true
284
+ else
285
+ return false
286
+ end
287
+ rescue Hpe3parSdk::HTTPNotFound => ex
288
+ return false
289
+ end
290
+ end
291
+ end
292
+ end
@@ -0,0 +1,126 @@
1
+ # (c) Copyright 2016-2017 Hewlett Packard Enterprise Development LP
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Unless required by applicable law or agreed to in writing, software distributed
8
+ # under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
9
+ # CONDITIONS OF ANY KIND, either express or implied. See the License for the
10
+ # specific language governing permissions and limitations under the License.
11
+
12
+ require_relative 'util'
13
+ require_relative 'constants'
14
+ require_relative 'models'
15
+
16
+ module Hpe3parSdk
17
+ class VolumeSetManager
18
+ def initialize(http, host_and_vv_set_filter_supported = false)
19
+ @http = http
20
+ @vv_set_filter_supported = host_and_vv_set_filter_supported
21
+ end
22
+
23
+ def find_all_volume_sets(name)
24
+ vv_sets = []
25
+ if @vv_set_filter_supported
26
+ query = %("setmembers EQ #{name}")
27
+ response = @http.get("/volumesets?query=#{query}")
28
+ volume_sets = response[1]['members']
29
+ volume_sets.each do |volume_set|
30
+ vv_sets.push(VolumeSet.new(volume_set))
31
+ end
32
+ else
33
+ volume_sets = get_volume_sets
34
+ volume_sets.each do |volume_set|
35
+ if !volume_set.setmembers.nil? && !volume_set.setmembers.empty? && volume_set.setmembers.include?(name)
36
+ vv_sets.push(volume_set)
37
+ end
38
+ end
39
+ end
40
+ vv_sets
41
+ end
42
+
43
+ def get_volume_sets
44
+ response = @http.get('/volumesets')
45
+ volume_set_members = []
46
+ response[1]['members'].each do |volume_set_member|
47
+ volume_set_members.push(VolumeSet.new(volume_set_member))
48
+ end
49
+ volume_set_members
50
+ end
51
+
52
+ def get_volume_set(name)
53
+ if name.nil? || name.strip.empty?
54
+ raise 'Volume set name cannot be nil or empty'
55
+ else
56
+ response = @http.get('/volumesets/' + name)
57
+ VolumeSet.new(response[1])
58
+ end
59
+ end
60
+
61
+ def create_volume_set(name, domain = nil, comment = nil, setmembers = nil)
62
+ info = { 'name' => name }
63
+
64
+ info['domain'] = domain if domain
65
+
66
+ info['comment'] = comment if comment
67
+
68
+ if setmembers
69
+ members = { 'setmembers' => setmembers }
70
+ info = Util.merge_hash(info, members)
71
+ end
72
+ @http.post('/volumesets', body: info)
73
+ end
74
+
75
+ def delete_volume_set(name)
76
+ @http.delete("/volumesets/#{name}")[1]
77
+ end
78
+
79
+ def modify_volume_set(name, action = nil, newName = nil, comment = nil, flash_cache_policy = nil, setmembers = nil)
80
+ info = {}
81
+
82
+ info['action'] = action if action
83
+
84
+ info['newName'] = newName if newName
85
+
86
+ info['comment'] = comment if comment
87
+
88
+ info['flashCachePolicy'] = flash_cache_policy if flash_cache_policy
89
+
90
+ if setmembers
91
+ members = { 'setmembers' => setmembers }
92
+ info = Util.merge_hash(info, members)
93
+ end
94
+
95
+ @http.put("/volumesets/#{name}", body: info)[1]
96
+ end
97
+
98
+ # QoS Priority Optimization methods
99
+ def add_volumes_to_volume_set(set_name, setmembers)
100
+ modify_volume_set(set_name, SetCustomAction::MEM_ADD, nil, nil, nil, setmembers)
101
+ end
102
+
103
+ def remove_volumes_from_volume_set(set_name, setmembers)
104
+ modify_volume_set(set_name, SetCustomAction::MEM_REMOVE, nil, nil, nil, setmembers)
105
+ end
106
+
107
+ def create_snapshot_of_volume_set(name, copy_of_name, optional = nil)
108
+ parameters = { 'name' => name }
109
+ parameters = Util.merge_hash(parameters, optional) if optional
110
+
111
+ info = { 'action' => 'createSnapshot', 'parameters' => parameters }
112
+
113
+ response = @http.post("/volumesets/#{copy_of_name}", body: info)
114
+ response[1]
115
+ end
116
+
117
+ def volume_set_exists?(name)
118
+ begin
119
+ get_volume_set(name)
120
+ return true
121
+ rescue Hpe3parSdk::HTTPNotFound => ex
122
+ return false
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,73 @@
1
+ # (c) Copyright 2016-2017 Hewlett Packard Enterprise Development LP
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Unless required by applicable law or agreed to in writing, software distributed
8
+ # under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
9
+ # CONDITIONS OF ANY KIND, either express or implied. See the License for the
10
+ # specific language governing permissions and limitations under the License.
11
+
12
+ module Hpe3parSdk
13
+ class WSAPIVersion
14
+ include Comparable
15
+ attr_accessor :major, :minor, :revision
16
+
17
+ def self.parse(version)
18
+ version_parts = version.split('.')
19
+ validate_version(version, version_parts)
20
+
21
+ @major = version_parts[0].to_i
22
+ @minor = version_parts[1].to_i
23
+ @revision = version_parts[2].to_i
24
+ obj_version = WSAPIVersion.new(@major, @minor, @revision)
25
+ return obj_version
26
+ end
27
+
28
+ def initialize(major, minor, revision)
29
+ @major = major
30
+ @minor = minor
31
+ @revision = revision
32
+ end
33
+
34
+ def <=>(other_version)
35
+ if major < other_version.major
36
+ return -1
37
+ end
38
+
39
+ if major > other_version.major
40
+ return 1
41
+ end
42
+
43
+ if minor < other_version.minor
44
+ return -1
45
+ end
46
+
47
+ if minor > other_version.minor
48
+ return 1
49
+ end
50
+
51
+ if revision < other_version.revision
52
+ return -1
53
+ end
54
+
55
+ if revision > other_version.revision
56
+ return 1
57
+ end
58
+
59
+ return 0
60
+ end
61
+
62
+ def to_s
63
+ major.to_s + '.' + minor.to_s + '.' + revision.to_s
64
+ end
65
+
66
+ private
67
+ def self.validate_version(version, version_parts)
68
+ if version_parts.length != 3
69
+ raise 'Invalid Version detected ' + version
70
+ end
71
+ end
72
+ end
73
+ end