softlayer_api 3.0.0 → 3.0.1

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.
@@ -50,10 +50,17 @@ module SoftLayer
50
50
  softlayer_client[:Ticket].createCancelServerTicket(self.id, cancel_reason, comment, true, 'HARDWARE')
51
51
  else
52
52
  # Note that reason and comment are ignored in this case, unfortunately
53
- softlayer_client[:Billing_Item].object_with_id(self.billingItem['id'].to_i).cancelService()
53
+ softlayer_client[:Billing_Item].object_with_id(self.service.object_mask("mask[id]").getBillingItem['id'].to_i).cancelService()
54
54
  end
55
55
  end
56
56
 
57
+ ##
58
+ # Returns the username/password combinations for remote management accounts
59
+ #
60
+ def remote_management_accounts
61
+ self['remoteManagementAccounts']
62
+ end
63
+
57
64
  ##
58
65
  # Returns the typical Service used to work with this Server
59
66
  # For Bare Metal Servers that is +SoftLayer_Hardware+ though in some special cases
@@ -69,17 +76,18 @@ module SoftLayer
69
76
  def self.default_object_mask
70
77
  sub_mask = {
71
78
  "mask(SoftLayer_Hardware_Server)" => [
72
- 'bareMetalInstanceFlag',
73
- 'provisionDate',
74
- 'hardwareStatus',
75
- 'memoryCapacity',
76
- 'processorPhysicalCoreAmount',
77
- 'networkManagementIpAddress',
78
- 'networkComponents[id, status, speed, maxSpeed, name, ipmiMacAddress, ipmiIpAddress, macAddress, primaryIpAddress, port, primarySubnet]',
79
- 'activeTransaction[id, transactionStatus[friendlyName,name]]',
80
- 'hardwareChassis[id, name]'
81
- ]
82
- }
79
+ 'activeTransaction[id, transactionStatus[friendlyName,name]]',
80
+ 'bareMetalInstanceFlag',
81
+ 'hardwareChassis[id, name]',
82
+ 'hardwareStatus',
83
+ 'memoryCapacity',
84
+ 'networkComponents[id, maxSpeed, name, ipmiIpAddress, ipmiMacAddress, macAddress, port, primaryIpAddress, primarySubnet, speed, status]',
85
+ 'networkManagementIpAddress',
86
+ 'processorPhysicalCoreAmount',
87
+ 'provisionDate',
88
+ 'remoteManagementAccounts[password,username]'
89
+ ]
90
+ }
83
91
 
84
92
  super.merge(sub_mask)
85
93
  end
@@ -249,4 +257,4 @@ module SoftLayer
249
257
  bare_metal_data.collect { |server_data| BareMetalServer.new(softlayer_client, server_data) }
250
258
  end
251
259
  end #BareMetalServer
252
- end
260
+ end
@@ -56,14 +56,27 @@ module SoftLayer
56
56
  # The following properties are optional, but allow further fine tuning of
57
57
  # the server
58
58
 
59
+ # Boolean, If true, an hourly server will be ordered, otherwise a monthly server will be ordered
60
+ # Corresponds to +useHourlyPricing+ in the SoftLayer_Container_Product_Order_Hardware_Server container
61
+ # documentation
62
+ attr_accessor :hourly
63
+
64
+ # An instance of the SoftLayer::ImageTemplate class. Represents the image template that should
65
+ # be installed on the server.
66
+ attr_accessor :image_template
67
+
68
+ # The URI of a script to execute on the server after it has been provisioned. This may be
69
+ # any object which accepts the to_s message. The resulting string will be passed to SoftLayer API.
70
+ attr_accessor :provision_script_URI
71
+
59
72
  # An array of the ids of SSH keys to install on the server upon provisioning
60
73
  # To obtain a list of existing SSH keys, call getSshKeys on the SoftLayer_Account service:
61
74
  # client[:Account].getSshKeys()
62
75
  attr_accessor :ssh_key_ids
63
76
 
64
- # The URI of a script to execute on the server after it has been provisioned. This may be
65
- # any object which accepts the to_s message. The resulting string will be passed to SoftLayer API.
66
- attr_accessor :provision_script_URI
77
+ # String, User metadata associated with the instance
78
+ # Corresponds to +userData+ in the +SoftLayer_Hardware_Server+ documentation
79
+ attr_accessor :user_metadata
67
80
 
68
81
  ##
69
82
  # You initialize a BareMetalServerOrder_Package by passing in the package that you
@@ -116,17 +129,21 @@ module SoftLayer
116
129
  # based on the configuration options given.
117
130
  def hardware_order
118
131
  product_order = {
119
- 'packageId' => @package.id,
120
- 'useHourlyPricing' => false,
121
- 'hardware' => [{
122
- 'hostname' => @hostname,
123
- 'domain' => @domain
124
- }]
132
+ 'packageId' => @package.id,
133
+ 'hardware' => [{
134
+ 'domain' => @domain,
135
+ 'hostname' => @hostname
136
+ }],
137
+ 'useHourlyPricing' => !!@hourly
125
138
  }
126
139
 
127
- product_order['location'] = @datacenter.id if @datacenter
128
- product_order['sshKeys'] = [{ 'sshKeyIds' => @ssh_key_ids }] if @ssh_key_ids
129
- product_order['provisionScripts'] = [@provision_script_URI.to_s] if @provision_script_URI
140
+ #Note that the use of image_template and SoftLayer::ProductPackage os/guest_diskX configuration category
141
+ #item prices is mutually exclusive.
142
+ product_order['hardware'][0]['userData'] = @user_metadata if @user_metadata
143
+ product_order['imageTemplateGlobalIdentifier'] = @image_template.global_id if @image_template
144
+ product_order['location'] = @datacenter.id if @datacenter
145
+ product_order['provisionScripts'] = [@provision_script_URI.to_s] if @provision_script_URI
146
+ product_order['sshKeys'] = [{ 'sshKeyIds' => @ssh_key_ids }] if @ssh_key_ids
130
147
 
131
148
  product_order['prices'] = @configuration_options.collect do |key, value|
132
149
  if value.respond_to?(:price_id)
@@ -141,4 +158,4 @@ module SoftLayer
141
158
  product_order
142
159
  end
143
160
  end # BareMetalServerOrder_Package
144
- end # SoftLayer
161
+ end # SoftLayer
@@ -95,7 +95,12 @@ module SoftLayer
95
95
  result[:username] = softlayer_section['username'] if softlayer_section['username']
96
96
  result[:endpoint_url] = softlayer_section['endpoint_url'] if softlayer_section['endpoint_url']
97
97
  result[:api_key] = softlayer_section['api_key'] if softlayer_section['api_key']
98
- result[:timeout] = softlayer_section['timeout'] if softlayer_section['timeout']
98
+
99
+ begin
100
+ result[:timeout] = Integer(softlayer_section['timeout']) if softlayer_section['timeout']
101
+ rescue => integer_parse_exception
102
+ $stderr.puts "Expected the value of the timeout configuration property, '#{result[:timeout]}', to be parseable as an integer"
103
+ end
99
104
  end
100
105
  end
101
106
  end
@@ -289,8 +289,8 @@ module SoftLayer
289
289
  end
290
290
 
291
291
  option_to_filter_path = {
292
- :name => "publicImages.name",
293
- :global_id => "publicImages.globalIdentifier",
292
+ :name => "name",
293
+ :global_id => "globalIdentifier",
294
294
  }
295
295
 
296
296
  # For each of the options in the option_to_filter_path map, if the options hash includes
@@ -299,10 +299,10 @@ module SoftLayer
299
299
  option_to_filter_path.each do |option, filter_path|
300
300
  object_filter.modify { |filter| filter.accept(filter_path).when_it is(options_hash[option])} if options_hash[option]
301
301
  end
302
-
302
+
303
303
  # Tags get a much more complex object filter operation so we handle them separately
304
304
  if options_hash.has_key?(:tags)
305
- object_filter.set_criteria_for_key_path("publicImages.tagReferences.tag.name", {
305
+ object_filter.set_criteria_for_key_path("tagReferences.tag.name", {
306
306
  'operation' => 'in',
307
307
  'options' => [{
308
308
  'name' => 'data',
@@ -359,7 +359,12 @@ module SoftLayer
359
359
  end
360
360
 
361
361
  ##
362
- # Retrieve the image template with the given global ID
362
+ # Retrieve the image template with the given global ID. The routine searches the public image template list first
363
+ # and the private image template list if no public image with the given id is found. If no template is found
364
+ # after searching both lists, then the function returns nil.
365
+ #
366
+ # Should either search return more than one result (meaning the system found more than one template with the same
367
+ # global_id), then the routine will throw an exception.
363
368
  #
364
369
  # The options parameter should contain:
365
370
  #
@@ -370,8 +375,13 @@ module SoftLayer
370
375
  #
371
376
  # The options may include the following keys
372
377
  # * <b>+:object_mask+</b> (string) - A object mask of properties, in addition to the default properties, that you wish to retrieve for the template
378
+ #
373
379
  def self.template_with_global_id(global_id, options_hash = {})
374
380
  templates = find_public_templates(options_hash.merge(:global_id => global_id))
381
+ if templates.empty? then
382
+ templates = find_private_templates(options_hash.merge(:global_id => global_id))
383
+ end
384
+ raise "ImageTemplate::template_with_global_id returned more than one template with the same global id. This should not happen" if templates != nil && templates.count > 1
375
385
  templates.empty? ? nil : templates[0]
376
386
  end
377
387
 
@@ -0,0 +1,130 @@
1
+ #--
2
+ # Copyright (c) 2014 SoftLayer Technologies, Inc. All rights reserved.
3
+ #
4
+ # For licensing information see the LICENSE.md file in the project root.
5
+ #++
6
+
7
+ module SoftLayer
8
+ ##
9
+ # Each SoftLayer NetworkMessageDelivery instance provides information about
10
+ # the username/password combination for a specific Network Message Delivery
11
+ # account.
12
+ #
13
+ # This class roughly corresponds to the entity SoftLayer_Network_Message_Delivery
14
+ # in the API.
15
+ #
16
+ class NetworkMessageDelivery < ModelBase
17
+ include ::SoftLayer::DynamicAttribute
18
+
19
+ ##
20
+ # :attr_reader:
21
+ # The date this username/password pair was created.
22
+ sl_attr :created, 'createDate'
23
+
24
+ ##
25
+ # :attr_reader:
26
+ # The date of the last modification to this username/password pair.
27
+ sl_attr :modified, 'modifyDate'
28
+
29
+ ##
30
+ # :attr_reader:
31
+ # The password part of the username/password pair.
32
+ sl_attr :password
33
+
34
+ ##
35
+ # :attr_reader:
36
+ # The username part of the username/password pair.
37
+ sl_attr :username
38
+
39
+ ##
40
+ # The message delivery type description of a network message delivery account.
41
+ sl_dynamic_attr :description do |resource|
42
+ resource.should_update? do
43
+ #only retrieved once per instance
44
+ @description == nil
45
+ end
46
+
47
+ resource.to_update do
48
+ type = self.service.getType
49
+ type['description']
50
+ end
51
+ end
52
+
53
+ ##
54
+ # The message delivery type name of a network message delivery account.
55
+ sl_dynamic_attr :name do |resource|
56
+ resource.should_update? do
57
+ #only retrieved once per instance
58
+ @name == nil
59
+ end
60
+
61
+ resource.to_update do
62
+ type = self.service.getType
63
+ type['name']
64
+ end
65
+ end
66
+
67
+ ##
68
+ # The vendor name for a network message delivery account.
69
+ sl_dynamic_attr :vendor do |resource|
70
+ resource.should_update? do
71
+ #only retrieved once per instance
72
+ @vendor == nil
73
+ end
74
+
75
+ resource.to_update do
76
+ vendor = self.service.getVendor
77
+ vendor['name']
78
+ end
79
+ end
80
+
81
+ ##
82
+ # Updates the password for the current account password.
83
+ #
84
+ def password=(password)
85
+ raise ArgumentError, "The new password cannot be nil" unless password
86
+ raise ArgumentError, "The new password cannot be empty" if password.empty?
87
+
88
+ self.service.editObject({ "password" => password.to_s })
89
+ self.refresh_details()
90
+ end
91
+
92
+ ##
93
+ # Returns the service for interacting with the network message delivery instance
94
+ # through the network API
95
+ #
96
+ def service
97
+ softlayer_client[:Network_Message_Delivery].object_with_id(self.id)
98
+ end
99
+
100
+ ##
101
+ # Make an API request to SoftLayer and return the latest properties hash
102
+ # for this object.
103
+ #
104
+ def softlayer_properties(object_mask = nil)
105
+ my_service = self.service
106
+
107
+ if(object_mask)
108
+ my_service = my_service.object_mask(object_mask)
109
+ else
110
+ my_service = my_service.object_mask(self.class.default_object_mask)
111
+ end
112
+
113
+ my_service.getObject()
114
+ end
115
+
116
+ protected
117
+
118
+ def self.default_object_mask
119
+ {
120
+ "mask(SoftLayer_Network_Message_Delivery)" => [
121
+ 'createDate',
122
+ 'id',
123
+ 'modifyDate',
124
+ 'password',
125
+ 'username'
126
+ ]
127
+ }.to_sl_object_mask
128
+ end
129
+ end
130
+ end #SoftLayer
@@ -0,0 +1,95 @@
1
+ #--
2
+ # Copyright (c) 2014 SoftLayer Technologies, Inc. All rights reserved.
3
+ #
4
+ # For licensing information see the LICENSE.md file in the project root.
5
+ #++
6
+
7
+ module SoftLayer
8
+ ##
9
+ # Each SoftLayer NetworkService instance provides connectivity
10
+ # information for a specific Network Service Resource.
11
+ #
12
+ # This class roughly corresponds to the entity SoftLayer_Network_Service_Resource
13
+ # in the API.
14
+ #
15
+ class NetworkService < ModelBase
16
+ include ::SoftLayer::DynamicAttribute
17
+
18
+ ##
19
+ # :attr_reader:
20
+ # The name associated with this resource
21
+ sl_attr :name
22
+
23
+ ##
24
+ # :attr_reader:
25
+ # The backend IP address for this resource
26
+ sl_attr :private_ip, 'backendIpAddress'
27
+
28
+ ##
29
+ # :attr_reader:
30
+ # The frontend IP address for this resource
31
+ sl_attr :public_ip, 'frontendIpAddress'
32
+
33
+ ##
34
+ # :attr_reader:
35
+ # The ssh username of for this resource
36
+ sl_attr :ssh_username, 'sshUsername'
37
+
38
+ ##
39
+ # Returns the datacenter that this network service resource is available in
40
+ sl_dynamic_attr :datacenter do |resource|
41
+ resource.should_update? do
42
+ #only retrieved once per instance
43
+ @datacenter == nil
44
+ end
45
+
46
+ resource.to_update do
47
+ Datacenter::datacenter_named(self['datacenter']['name'], self.softlayer_client)
48
+ end
49
+ end
50
+
51
+ ##
52
+ # Returns the api properties used to connect to the network service resource
53
+ #
54
+ def api
55
+ {
56
+ 'host' => self['apiHost'],
57
+ 'password' => self['apiPassword'],
58
+ 'path' => self['apiPath'],
59
+ 'port' => self['apiPort'],
60
+ 'protocol' => self['apiProtocol'],
61
+ 'username' => self['apiUsername']
62
+ }
63
+ end
64
+
65
+ ##
66
+ # Returns the network service resource type name
67
+ #
68
+ def type
69
+ self['type']['type']
70
+ end
71
+
72
+ protected
73
+
74
+ def self.default_object_mask
75
+ {
76
+ "mask(SoftLayer_Network_Service_Resource)" => [
77
+ 'apiHost',
78
+ 'apiPassword',
79
+ 'apiPath',
80
+ 'apiPort',
81
+ 'apiProtocol',
82
+ 'apiUsername',
83
+ 'backendIpAddress',
84
+ 'datacenter',
85
+ 'frontendIpAddress',
86
+ 'id',
87
+ 'name',
88
+ 'networkDevice.id',
89
+ 'sshUsername',
90
+ 'type.type'
91
+ ]
92
+ }.to_sl_object_mask
93
+ end
94
+ end
95
+ end #SoftLayer
@@ -0,0 +1,340 @@
1
+ #--
2
+ # Copyright (c) 2014 SoftLayer Technologies, Inc. All rights reserved.
3
+ #
4
+ # For licensing information see the LICENSE.md file in the project root.
5
+ #++
6
+
7
+ module SoftLayer
8
+ ##
9
+ # Each SoftLayer NetworkStorage instance provides information about
10
+ # a storage product and access credentials.
11
+ #
12
+ # This class roughly corresponds to the entity SoftLayer_Network_Storage
13
+ # in the API.
14
+ #
15
+ class NetworkStorage < ModelBase
16
+ include ::SoftLayer::DynamicAttribute
17
+
18
+ ##
19
+ # :attr_reader:
20
+ # A Storage account's capacity, measured in gigabytes.
21
+ sl_attr :capacity, 'capacityGb'
22
+
23
+ ##
24
+ # :attr_reader:
25
+ # The date a network storage volume was created.
26
+ sl_attr :created, 'createDate'
27
+
28
+ ##
29
+ # :attr_reader:
30
+ # Public notes related to a Storage volume.
31
+ sl_attr :notes
32
+
33
+ ##
34
+ # :attr_reader:
35
+ # The password used to access a non-EVault Storage volume.
36
+ # This password is used to register the EVault server agent with the
37
+ # vault backup system.
38
+ sl_attr :password
39
+
40
+ ##
41
+ # :attr_reader:
42
+ # A Storage account's type.
43
+ sl_attr :type, 'nasType'
44
+
45
+ ##
46
+ # :attr_reader:
47
+ # This flag indicates whether this storage type is upgradable or not.
48
+ sl_attr :upgradable, 'upgradableFlag'
49
+
50
+ ##
51
+ # :attr_reader:
52
+ # The username used to access a non-EVault Storage volume.
53
+ # This username is used to register the EVault server agent with the
54
+ # vault backup system.
55
+ sl_attr :username
56
+
57
+ ##
58
+ # Other usernames and passwords associated with a Storage volume.
59
+ sl_dynamic_attr :account_password do |resource|
60
+ resource.should_update? do
61
+ #only retrieved once per instance
62
+ @account_password == nil
63
+ end
64
+
65
+ resource.to_update do
66
+ account_password = self.service.object_mask(AccountPassword.default_object_mask).getAccountPassword
67
+ AccountPassword.new(softlayer_client, account_password) unless account_password.empty?
68
+ end
69
+ end
70
+
71
+ ##
72
+ # A Storage volume's access credentials.
73
+ sl_dynamic_attr :credentials do |resource|
74
+ resource.should_update? do
75
+ #only retrieved once per instance
76
+ @credentials == nil
77
+ end
78
+
79
+ resource.to_update do
80
+ self.service.object_mask(NetworkStorageCredential.default_object_mask).getCredentials.collect{|cred| NetworkStorageCredential.new(softlayer_client, cred) }
81
+ end
82
+ end
83
+
84
+ ##
85
+ # The network resource a Storage service is connected to.
86
+ sl_dynamic_attr :service_resource do |resource|
87
+ resource.should_update? do
88
+ #only retrieved once per instance
89
+ @service_resource == nil
90
+ end
91
+
92
+ resource.to_update do
93
+ NetworkService.new(softlayer_client, self.service.object_mask(NetworkService.default_object_mask).getServiceResource)
94
+ end
95
+ end
96
+
97
+ ##
98
+ # The account username and password for the EVault webCC interface.
99
+ sl_dynamic_attr :webcc_account do |resource|
100
+ resource.should_update? do
101
+ #only retrieved once per instance
102
+ @webcc_account == nil
103
+ end
104
+
105
+ resource.to_update do
106
+ webcc_account = self.service.object_mask(AccountPassword.default_object_mask).getWebccAccount
107
+ AccountPassword.new(softlayer_client, webcc_account) unless webcc_account.empty?
108
+ end
109
+ end
110
+
111
+ ##
112
+ # Add a username/password credential to the network storage instance
113
+ #
114
+ def add_credential(credential_type)
115
+ raise ArgumentError, "The new credential type cannot be nil" unless credential_type
116
+ raise ArgumentError, "The new credential type cannot be empty" if credential_type.empty?
117
+
118
+ new_credential = self.service.object_mask(NetworkStorageCredential.default_object_mask).assignNewCredential(credential_type.to_s)
119
+
120
+ @credentials = nil
121
+
122
+ NetworkStorageCredential.new(softlayer_client, new_credential) unless new_credential.empty?
123
+ end
124
+
125
+ ##
126
+ # Assign an existing network storage credential specified by the username to the network storage instance
127
+ #
128
+ def assign_credential(username)
129
+ raise ArgumentError, "The username cannot be nil" unless username
130
+ raise ArgumentError, "The username cannot be empty" if username.empty?
131
+
132
+ self.service.assignCredential(username.to_s)
133
+
134
+ @credentials = nil
135
+ end
136
+
137
+ ##
138
+ # Determines if one of the credentials pertains to the specified username.
139
+ #
140
+ def has_user_credential?(username)
141
+ self.credentials.map { |credential| credential.username }.include?(username)
142
+ end
143
+
144
+ ##
145
+ # Updates the notes for the network storage instance.
146
+ #
147
+ def notes=(notes)
148
+ self.service.editObject({ "notes" => notes.to_s })
149
+ self.refresh_details()
150
+ end
151
+
152
+ ##
153
+ # Updates the password for the network storage instance.
154
+ #
155
+ def password=(password)
156
+ raise ArgumentError, "The new password cannot be nil" unless password
157
+ raise ArgumentError, "The new password cannot be empty" if password.empty?
158
+
159
+ self.service.editObject({ "password" => password.to_s })
160
+ self.refresh_details()
161
+ end
162
+
163
+ ##
164
+ # Remove an existing network storage credential specified by the username from the network storage instance
165
+ #
166
+ def remove_credential(username)
167
+ raise ArgumentError, "The username cannot be nil" unless username
168
+ raise ArgumentError, "The username cannot be empty" if username.empty?
169
+
170
+ self.service.removeCredential(username.to_s)
171
+
172
+ @credentials = nil
173
+ end
174
+
175
+ ##
176
+ # Retrieve a list of network storage services.
177
+ #
178
+ # The options parameter should contain:
179
+ #
180
+ # <b>+:client+</b> - The client used to connect to the API
181
+ #
182
+ # If no client is given, then the routine will try to use Client.default_client
183
+ # If no client can be found the routine will raise an error.
184
+ #
185
+ # You may filter the list returned by adding options:
186
+ # * <b>+:datacenter+</b> (string) - Include network storage associated with servers matching this datacenter
187
+ # * <b>+:domain+</b> (string) - Include network storage associated with servers matching this domain
188
+ # * <b>+:hostname+</b> (string) - Include network storage associated with servers matching this hostname
189
+ # * <b>+:network_storage_server_type+</b> (string) - Include network storage associated with this server type
190
+ # * <b>+:network_storage_type+</b> (string) - Include network storage from devices of this storage type
191
+ # * <b>+:service+</b> (string) - Include network storage from devices with this service fqdn
192
+ # * <b>+:tags+</b> (Array) - Include network storage associated with servers matching these tags
193
+ #
194
+ def self.find_network_storage(options_hash = {})
195
+ softlayer_client = options_hash[:client] || Client.default_client
196
+ raise "#{__method__} requires a client but none was given and Client::default_client is not set" if !softlayer_client
197
+
198
+ if(options_hash.has_key? :network_storage_object_filter)
199
+ network_storage_object_filter = options_hash[:network_storage_object_filter]
200
+ raise "Expected an instance of SoftLayer::ObjectFilter" unless network_storage_object_filter.kind_of?(SoftLayer::ObjectFilter)
201
+ else
202
+ network_storage_object_filter = ObjectFilter.new()
203
+ end
204
+
205
+ if options_hash.has_key?(:network_storage_server_type) && ! [ :hardware, :virtual_server ].include?(options_hash[:network_storage_server_type])
206
+ raise "Expected one of :hardware or :virtual_server for :network_storage_server_type option in #{__method__}"
207
+ end
208
+
209
+ filter_label = {
210
+ :evault => "evaultNetworkStorage",
211
+ :hardware => "hardware",
212
+ :hub => "hubNetworkStorage",
213
+ :iscsi => "iscsiNetworkStorage",
214
+ :lockbox => "lockboxNetworkStorage",
215
+ :nas => "nasNetworkStorage",
216
+ :network_storage => "networkStorage",
217
+ :virtual_server => "virtualGuest"
218
+ }
219
+
220
+ option_to_filter_path = {
221
+ :datacenter => lambda { |storage_type, server_type| return [ filter_label[storage_type], '.', filter_label[server_type], '.datacenter.name' ].join },
222
+ :domain => lambda { |storage_type, server_type| return [ filter_label[storage_type], '.', filter_label[server_type], '.domain' ].join },
223
+ :hostname => lambda { |storage_type, server_type| return [ filter_label[storage_type], '.', filter_label[server_type], '.hostname' ].join },
224
+ :service => lambda { |storage_type| return [ filter_label[storage_type], '.serviceResource.backendIpAddress' ].join },
225
+ :tags => lambda { |storage_type, server_type| return [ filter_label[storage_type], '.', filter_label[server_type], '.tagReferences.tag.name' ].join },
226
+ }
227
+
228
+ if options_hash[:network_storage_type]
229
+ unless filter_label.select{|label,filter| filter.end_with?("Storage")}.keys.include?(options_hash[:network_storage_type])
230
+ raise "Expected :evault, :hub, :iscsi, :lockbox, :nas or :network_storage for option :network_storage_type in #{__method__}"
231
+ end
232
+ end
233
+
234
+ network_storage_type = options_hash[:network_storage_type] || :network_storage
235
+
236
+ if options_hash[:service]
237
+ network_storage_object_filter.modify do |filter|
238
+ filter.accept(option_to_filter_path[:service].call(network_storage_type)).when_it is(options_hash[:service])
239
+ end
240
+ end
241
+
242
+ if options_hash[:network_storage_server_type]
243
+ [ :datacenter, :domain, :hostname ].each do |option|
244
+ if options_hash[option]
245
+ network_storage_object_filter.modify do |filter|
246
+ filter.accept(option_to_filter_path[option].call(network_storage_type, options_hash[:network_storage_server_type])).when_it is(options_hash[option])
247
+ end
248
+ end
249
+ end
250
+
251
+ if options_hash[:tags]
252
+ network_storage_object_filter.set_criteria_for_key_path(option_to_filter_path[:tags].call(network_storage_type, options_hash[:network_storage_server_type]),
253
+ {
254
+ 'operation' => 'in',
255
+ 'options' => [{
256
+ 'name' => 'data',
257
+ 'value' => options_hash[:tags].collect{ |tag_value| tag_value.to_s }
258
+ }]
259
+ })
260
+ end
261
+ end
262
+
263
+ account_service = softlayer_client[:Account]
264
+ account_service = account_service.object_filter(network_storage_object_filter) unless network_storage_object_filter.empty?
265
+ account_service = account_service.object_mask(NetworkStorage.default_object_mask)
266
+ account_service = account_service.object_mask(options_hash[:network_storage_object_mask]) if options_hash[:network_storage_object_mask]
267
+
268
+ case options_hash[:network_storage_type]
269
+ when :evault
270
+ network_storage_data = account_service.getEvaultNetworkStorage
271
+ when :hub
272
+ network_storage_data = account_service.getHubNetworkStorage
273
+ when :iscsi
274
+ network_storage_data = account_service.getIscsiNetworkStorage
275
+ when :lockbox
276
+ network_storage_data = account_service.getLockboxNetworkStorage
277
+ when :nas
278
+ network_storage_data = account_service.getNasNetworkStorage
279
+ when :network_storage, nil
280
+ network_storage_data = account_service.getNetworkStorage
281
+ end
282
+
283
+ network_storage_data.collect { |network_storage| NetworkStorage.new(softlayer_client, network_storage) unless network_storage.empty? }.compact
284
+ end
285
+
286
+ ##
287
+ # Returns the service for interacting with this network storage through the network API
288
+ #
289
+ def service
290
+ softlayer_client[:Network_Storage].object_with_id(self.id)
291
+ end
292
+
293
+ ##
294
+ # Make an API request to SoftLayer and return the latest properties hash
295
+ # for this object.
296
+ #
297
+ def softlayer_properties(object_mask = nil)
298
+ my_service = self.service
299
+
300
+ if(object_mask)
301
+ my_service = my_service.object_mask(object_mask)
302
+ else
303
+ my_service = my_service.object_mask(self.class.default_object_mask)
304
+ end
305
+
306
+ my_service.getObject()
307
+ end
308
+
309
+ ##
310
+ # Updates the password for the network storage credential of the username specified.
311
+ #
312
+ def update_credential_password(username, password)
313
+ raise ArgumentError, "The new password cannot be nil" unless password
314
+ raise ArgumentError, "The new username cannot be nil" unless username
315
+ raise ArgumentError, "The new password cannot be empty" if password.empty?
316
+ raise ArgumentError, "The new username cannot be empty" if username.empty?
317
+
318
+ self.service.editCredential(username.to_s, password.to_s)
319
+
320
+ @credentials = nil
321
+ end
322
+
323
+ protected
324
+
325
+ def self.default_object_mask
326
+ {
327
+ "mask(SoftLayer_Network_Storage)" => [
328
+ 'capacityGb',
329
+ 'createDate',
330
+ 'id',
331
+ 'nasType',
332
+ 'notes',
333
+ 'password',
334
+ 'upgradableFlag',
335
+ 'username'
336
+ ]
337
+ }.to_sl_object_mask
338
+ end
339
+ end
340
+ end #SoftLayer