Class: SoftLayer::ImageTemplate

Inherits:
ModelBase show all
Defined in:
lib/softlayer/ImageTemplate.rb

Overview

A Virtual Server Image Template.

This class rougly corresponds to the unwieldily named SoftLayer_Virtual_Guest_Block_Device_Template_Group service:

sldn.softlayer.com/reference/services/SoftLayer_Virtual_Guest_Block_Device_Template_Group

Instance Attribute Summary

Attributes inherited from ModelBase

#softlayer_client

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from ModelBase

#[], #has_sl_property?, #initialize, #refresh_details, sl_attr, #to_ary

Constructor Details

This class inherits a constructor from SoftLayer::ModelBase

Class Method Details

.find_private_templates(options_hash = {}) ⇒ Object

Retrieve a list of the private image templates from the account.

The options parameter should contain:

:client - The client used to connect to the API

If no client is given, then the routine will try to use Client.default_client. If no client can be found the routine will raise an error.

Additional options that may be provided:

  • :name (string) - Return templates with the given name

  • :global_id (string) - Return templates with the given global identfier


214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/softlayer/ImageTemplate.rb', line 214

def self.find_private_templates(options_hash = {})
  softlayer_client = options_hash[:client] || Client.default_client
  raise "#{__method__} requires a client but none was given and Client::default_client is not set" if !softlayer_client

  if(options_hash.has_key? :object_filter)
    object_filter = options_hash[:object_filter]
    raise "Expected an instance of SoftLayer::ObjectFilter" unless object_filter.kind_of?(SoftLayer::ObjectFilter)
  else
    object_filter = ObjectFilter.new()
  end

  option_to_filter_path = {
    :name => "privateBlockDeviceTemplateGroups.name",
    :global_id => "privateBlockDeviceTemplateGroups.globalIdentifier",
  }

  # For each of the options in the option_to_filter_path map, if the options hash includes
  # that particular option, add a clause to the object filter that filters for the matching
  # value
  option_to_filter_path.each do |option, filter_path|
    object_filter.modify { |filter| filter.accept(filter_path).when_it is(options_hash[option])} if options_hash[option]
  end

  # Tags get a much more complex object filter operation so we handle them separately
  if options_hash.has_key?(:tags)
    object_filter.set_criteria_for_key_path("privateBlockDeviceTemplateGroups.tagReferences.tag.name", {
      'operation' => 'in',
      'options' => [{
        'name' => 'data',
        'value' => options_hash[:tags].collect{ |tag_value| tag_value.to_s }
        }]
      } );
  end

   = softlayer_client[:Account]
   = .object_filter(object_filter) unless object_filter.empty?
   = .object_mask(default_object_mask)

  if options_hash.has_key? :object_mask
     = .object_mask(options_hash[:object_mask])
  end

  if options_hash.has_key?(:result_limit)
    offset = options[:result_limit][:offset]
    limit = options[:result_limit][:limit]

     = .result_limit(offset, limit)
  end

  templates_data = .getPrivateBlockDeviceTemplateGroups
  templates_data.collect { |template_data| new(softlayer_client, template_data) }
end

.find_public_templates(options_hash = {}) ⇒ Object

Retrieve a list of public image templates

The options parameter should contain:

:client - The client used to connect to the API

If no client is given, then the routine will try to use Client.default_client If no client can be found the routine will raise an error.

Additional options that may be provided:

  • :name (string) - Return templates with the given name

  • :global_id (string) - Return templates with the given global identfier


280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/softlayer/ImageTemplate.rb', line 280

def self.find_public_templates(options_hash = {})
  softlayer_client = options_hash[:client] || Client.default_client
  raise "#{__method__} requires a client but none was given and Client::default_client is not set" if !softlayer_client

  if(options_hash.has_key? :object_filter)
    object_filter = options_hash[:object_filter]
    raise "Expected an instance of SoftLayer::ObjectFilter" unless object_filter.kind_of?(SoftLayer::ObjectFilter)
  else
    object_filter = ObjectFilter.new()
  end

  option_to_filter_path = {
    :name => "publicImages.name",
    :global_id => "publicImages.globalIdentifier",
  }

  # For each of the options in the option_to_filter_path map, if the options hash includes
  # that particular option, add a clause to the object filter that filters for the matching
  # value
  option_to_filter_path.each do |option, filter_path|
    object_filter.modify { |filter| filter.accept(filter_path).when_it is(options_hash[option])} if options_hash[option]
  end

  # Tags get a much more complex object filter operation so we handle them separately
  if options_hash.has_key?(:tags)
    object_filter.set_criteria_for_key_path("publicImages.tagReferences.tag.name", {
      'operation' => 'in',
      'options' => [{
        'name' => 'data',
        'value' => options_hash[:tags].collect{ |tag_value| tag_value.to_s }
        }]
      } );
  end

  template_service = softlayer_client[:Virtual_Guest_Block_Device_Template_Group]
  template_service = template_service.object_filter(object_filter) unless object_filter.empty?
  template_service = template_service.object_mask(default_object_mask)

  if options_hash.has_key? :object_mask
    template_service = template_service.object_mask(options_hash[:object_mask])
  end

  if options_hash.has_key?(:result_limit)
    offset = options[:result_limit][:offset]
    limit = options[:result_limit][:limit]

    template_service = template_service.result_limit(offset, limit)
  end

  templates_data = template_service.getPublicImages
  templates_data.collect { |template_data| new(softlayer_client, template_data) }
end

.template_with_global_id(global_id, options_hash = {}) ⇒ Object

Retrieve the image template with the given global ID

The options parameter should contain:

:client - The client used to connect to the API

If no client is given, then the routine will try to use Client.default_client If no client can be found the routine will raise an error.

The options may include the following keys

  • :object_mask (string) - A object mask of properties, in addition to the default properties, that you wish to retrieve for the template


373
374
375
376
# File 'lib/softlayer/ImageTemplate.rb', line 373

def self.template_with_global_id(global_id, options_hash = {})
  templates = find_public_templates(options_hash.merge(:global_id => global_id))
  templates.empty? ? nil : templates[0]
end

.template_with_id(id, options_hash = {}) ⇒ Object

Retrive the Image Template with the given ID (Note! This is the service ID, not the globalIdentifier!)

The options parameter should contain:

:client - The client used to connect to the API

If no client is given, then the routine will try to use Client.default_client If no client can be found the routine will raise an error.

The options may include the following keys

  • :object_mask (string) - A object mask of properties, in addition to the default properties, that you wish to retrieve for the template


346
347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/softlayer/ImageTemplate.rb', line 346

def self.template_with_id(id, options_hash = {})
  softlayer_client = options_hash[:client] || Client.default_client
  raise "#{__method__} requires a client but none was given and Client::default_client is not set" if !softlayer_client

  service = softlayer_client[:Virtual_Guest_Block_Device_Template_Group].object_with_id(id)
  service.object_mask(default_object_mask)

  if options_hash.has_key? :object_mask
    service = service.object_mask(options_hash[:object_mask])
  end

  template_data = service.getObject
  new(softlayer_client, template_data)
end

Instance Method Details

#available_datacentersObject

Returns an array of the datacenters that this image can be stored in. This is the set of datacenters that you may choose from, when putting together a list you will send to the datacenters= setter.


108
109
110
111
# File 'lib/softlayer/ImageTemplate.rb', line 108

def available_datacenters
  datacenters_data = self.service.getStorageLocations()
  datacenters_data.collect { |datacenter_data| SoftLayer::Datacenter.datacenter_named(datacenter_data['name']) }
end

#datacentersObject

Returns the an array containing the datacenters where this image is available.


80
81
82
# File 'lib/softlayer/ImageTemplate.rb', line 80

def datacenters
  self['datacenters'].collect{ |datacenter_data| SoftLayer::Datacenter.datacenter_named(datacenter_data['name'])}
end

#datacenters=(datacenters_array) ⇒ Object

Accepts an array of datacenters (instances of SoftLayer::Datacenter) where this image should be made available. The call will kick off one or more transactions to make the image available in the given datacenters. These transactions can take some time to complete.

Note that the template will be REMOVED from any datacenter that does not appear in this array! The list given must be comprehensive.

The available_datacenters call returns a list of the values that are valid whithin this array.


95
96
97
98
99
100
101
# File 'lib/softlayer/ImageTemplate.rb', line 95

def datacenters=(datacenters_array)
  datacenter_data = datacenters_array.collect do |datacenter|
    { "id" => datacenter.id }
  end

  self.service.setAvailableLocations(datacenter_data.compact)
end

#delete!Object

Creates a transaction to delete the image template and all the disk images associated with it.

This is a final action and cannot be undone. the transaction will proceed immediately.

Call it with extreme care!


158
159
160
# File 'lib/softlayer/ImageTemplate.rb', line 158

def delete!
  self.service.deleteObject
end

#flex_image?Boolean

true if the image template is a flex image Note that the flexImageFlag property comes back as a boolean

Returns:

  • (Boolean)

50
51
52
# File 'lib/softlayer/ImageTemplate.rb', line 50

def flex_image?
  !!self['flexImageFlag']
end

#global_idObject

:attr_reader: The universally unique identifier (if any) for the template. Can be nil.


33
# File 'lib/softlayer/ImageTemplate.rb', line 33

sl_attr :global_id, 'globalIdentifier'

#nameObject

:attr_reader: The 'friendly name' given to the template when it was created


23
# File 'lib/softlayer/ImageTemplate.rb', line 23

sl_attr :name

#notesObject

:attr_reader: The notes, if any, that are attached to the template. Can be nil.


28
# File 'lib/softlayer/ImageTemplate.rb', line 28

sl_attr :notes, "note"

#notes=(new_notes) ⇒ Object

Changes the notes on an template to be the given strings


56
57
58
59
60
61
# File 'lib/softlayer/ImageTemplate.rb', line 56

def notes=(new_notes)
  # it is not a typo that this sets the "note" property.  The
  # property in the network api is "note", the model exposes it as
  # 'notes' for self-consistency
  self.service.editObject({ "note" => new_notes.to_s})
end

#public?Boolean

true if the image template is a flex image Note that the publicFlag property comes back as an integer (0 or 1)

Returns:

  • (Boolean)

43
44
45
# File 'lib/softlayer/ImageTemplate.rb', line 43

def public?
  self['publicFlag'] != 0
end

#rename!(new_name) ⇒ Object

Change the name of the template


36
37
38
# File 'lib/softlayer/ImageTemplate.rb', line 36

def rename!(new_name)
  self.service.editObject({ "name" => new_name.to_s})
end

#serviceObject

ModelBase protocol methods


193
194
195
# File 'lib/softlayer/ImageTemplate.rb', line 193

def service
  softlayer_client[:Virtual_Guest_Block_Device_Template_Group].object_with_id(self.id)
end

#shared_with_accountsObject

Returns a list of the accounts (identified by account ID numbers) that this image is shared with


117
118
119
120
# File 'lib/softlayer/ImageTemplate.rb', line 117

def shared_with_accounts
  accounts_data = self.service.getAccountReferences
  accounts_data.collect { || ['accountId'] }
end

#shared_with_accounts=(account_id_list) ⇒ Object

Change the set of accounts that this image is shared with. The parameter is an array of account ID's.

Note that this routine will “unshare” with any accounts not included in the list passed in so the list should be comprehensive


130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/softlayer/ImageTemplate.rb', line 130

def shared_with_accounts= ()
  already_sharing_with = self.shared_with_accounts

  accounts_to_add = .select { || !already_sharing_with.include?() }

  # Note, using the network API, it is possible to "unshare" an image template
  # with the account that owns it, however, this leads to a rather odd state
  # where the image has allocated resources (that the account may be charged for)
  # but no way to delete those resources. For that reason this model
  # always includes the account ID that owns the image in the list of
  # accounts the image will be shared with.
   = self['accountId']
  accounts_to_add.push() if !already_sharing_with.include?() && !accounts_to_add.include?()

  accounts_to_remove = already_sharing_with.select { || ( != ) && !.include?() }

  accounts_to_add.each {|| self.service.permitSharingAccess  }
  accounts_to_remove.each {|| self.service.denySharingAccess  }
end

#softlayer_properties(object_mask = nil) ⇒ Object


197
198
199
# File 'lib/softlayer/ImageTemplate.rb', line 197

def softlayer_properties(object_mask = nil)
  self.service.object_mask(self.class.default_object_mask).getObject
end

#tagsObject

Returns an array of the tags set on the image


65
66
67
# File 'lib/softlayer/ImageTemplate.rb', line 65

def tags
  return self['tagReferences'].collect{ |tag_reference| tag_reference['tag']['name'] }
end

#tags=(tags_array) ⇒ Object

Sets the tags on the template. Note: a pre-existing tag will be removed from the template if it does not appear in the array given. The list of tags must be comprehensive.


73
74
75
76
# File 'lib/softlayer/ImageTemplate.rb', line 73

def tags=(tags_array)
  as_strings = tags_array.collect { |tag| tag.to_s }
  self.service.setTags(as_strings.join(','))
end

#wait_until_ready(max_trials, seconds_between_tries = 2) ⇒ Object

Repeatedly poll the netwokr API until transactions related to this image template are finished

A template is not 'ready' until all the transactions on the template itself, and all its children are complete.

At each trial, the routine will yield to a block if one is given The block is passed one parameter, a boolean flag indicating whether or not the image template is 'ready'.


173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/softlayer/ImageTemplate.rb', line 173

def wait_until_ready(max_trials, seconds_between_tries = 2)
  # pessimistically assume the server is not ready
  num_trials = 0
  begin
    self.refresh_details()

    parent_ready = !(has_sl_property? :transactionId) || (self[:transactionId] == "")
    children_ready = (nil == self['children'].find { |child| child['transactionId'] != "" })

    ready = parent_ready && children_ready
    yield ready if block_given?

    num_trials = num_trials + 1
    sleep(seconds_between_tries) if !ready && (num_trials <= max_trials)
  end until ready || (num_trials >= max_trials)

  ready
end