Class: SoftLayer::ImageTemplate

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

Overview

A Virtual Server Image Template.

This class roughly 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/array) - Return templates with the given name

  • :global_id (string/array) - Return templates with the given global identifier

  • :tags (string/array) - Return templates with the tags

Additionally you may provide options related to the request itself:

  • :object_filter (ObjectFilter) - Include private image templates for templates that matche the

    criteria of this object filter
    
  • :object_mask (string, hash, or array) - The object mask of properties you wish to receive for the items returned.

    If not provided, the result will use the default object mask
    
  • :result_limit (hash with :limit, and :offset keys) - Limit the scope of results returned.



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
# File 'lib/softlayer/ImageTemplate.rb', line 223

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",
    :tags      => "privateBlockDeviceTemplateGroups.tagReferences.tag.name"
  }

  # 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

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

  if options_hash[:result_limit] && options_hash[:result_limit][:offset] && options_hash[:result_limit][:limit]
     = .result_limit(options_hash[:result_limit][:offset], options_hash[:result_limit][:limit])
  end

  templates_data = .getPrivateBlockDeviceTemplateGroups
  templates_data.collect { |template_data| ImageTemplate.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/array) - Return templates with the given name

  • :global_id (string/array) - Return templates with the given global identifier

  • :tags (string/array) - Return templates with the tags

Additionally you may provide options related to the request itself:

  • :object_filter (ObjectFilter) - Include public image templates for templates that matche the

    criteria of this object filter
    
  • :object_mask (string, hash, or array) - The object mask of properties you wish to receive for the items returned.

    If not provided, the result will use the default object mask
    
  • :result_limit (hash with :limit, and :offset keys) - Limit the scope of results returned.



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
# File 'lib/softlayer/ImageTemplate.rb', line 282

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      => "name",
    :global_id => "globalIdentifier",
    :tags      => "tagReferences.tag.name"
  }

  # 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

  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)
  template_service = template_service.object_mask(options_hash[:object_mask]) if options_hash[:object_mask]

  if options_hash[:result_limit] && options_hash[:result_limit][:offset] && options_hash[:result_limit][:limit]
    template_service = template_service.result_limit(options_hash[:result_limit][:offset], options_hash[:result_limit][:limit])
  end

  templates_data = template_service.getPublicImages
  templates_data.collect { |template_data| ImageTemplate.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 routine searches the public image template list first and the private image template list if no public image with the given id is found. If no template is found after searching both lists, then the function returns nil.

Should either search return more than one result (meaning the system found more than one template with the same global_id), then the routine will throw an exception.

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



362
363
364
365
366
367
368
369
# File 'lib/softlayer/ImageTemplate.rb', line 362

def self.template_with_global_id(global_id, options_hash = {})
  templates = find_public_templates(options_hash.merge(:global_id => global_id))
  if templates.empty? then
    templates = find_private_templates(options_hash.merge(:global_id => global_id))
  end
  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
  templates.empty? ? nil : templates[0]
end

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

Retrieve 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



332
333
334
335
336
337
338
339
340
341
342
# File 'lib/softlayer/ImageTemplate.rb', line 332

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 = service.object_mask(default_object_mask)
  service = service.object_mask(options_hash[:object_mask]) if options_hash[:object_mask]

  template_data = service.getObject
  ImageTemplate.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 within 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: global_id 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: notes 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 network 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