Skip to content

Commit c521644

Browse files
committed
Propogate the DataCenter and ImageTemplate models so they are used consistently in the API. Made notes in the changelog about the changes.
1 parent 20f9d6c commit c521644

14 files changed

Lines changed: 98 additions & 79 deletions

CHANGELOG.textile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
*3.0*
22
* Added a method to reboot servers.
3-
* Added a model for Virtual Server Image Templates
4-
* Substantially rewrote the ObjectFilter class.
3+
* Substantially rewrote the ObjectFilter class. ObjectFilters used to be hashes which made it easy to manipulate their content incorrectly. The new implementation has a strict interface that makes it harder to manipulate filters incorrectly.
4+
* Added a model for Virtual Server Image Templates (SoftLayer::ImageTemplate) - VirtualServerOrder now requires an instance of this class rather than allowing you to provide just the global_id of an image
5+
* Added a model for data centers (SoftLayer::Datacenter). Bare Metal, Bare Metal Package, and Virtual server orders now use an instance of Datacenter to identify where their servers will be provisioned. The routines in those classes which used to provide lists of valid data center names now return data center objects.
56

67
*2.1.1*
78
* Virtual server upgrades no longer raise exceptions

doc_src/Contribution Guide.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Any requests for enhancements, new features, or bug reports should be entered in
88

99
# Development Environment
1010

11-
As a Ruby project, your first step will be to install the [Ruby Programming Language](https://www.ruby-lang.org/en/). Many Unix-derived environments, including Mac OS X, have a version or Ruby installed by default, however, the default version may be out-of-date. Please visit the main Ruby language [site](https://www.ruby-lang.org/en/) for instructions on installing an up-to-date build of Ruby for your computing environment.
11+
As a Ruby project, your first step will be to install the [Ruby Programming Language](https://www.ruby-lang.org/en/). Many Unix-derived environments, including Mac OS X, have a version or Ruby installed by default, however, the default version may be out-of-date. Please visit the main Ruby language [site](https://www.ruby-lang.org/en/) for instructions on installing an up-to-date build of Ruby for your computing environment.
1212

1313
The Gem supports multiple versions of Ruby, and we recommend using Ruby 2.0 or later. The [Ruby Version Manager (rvm)](https://rvm.io) is an invaluable tool to help keep track of multiple versions of Ruby. The Gem no longer supports Ruby 1.8.7. Support for Ruby 1.9 will continue for a time, but the Core Ruby team is already withdrawing their support for that version.
1414

@@ -93,7 +93,7 @@ The basic directory structure for the source tree is as follows
9393
softlayer # Folder containing most of the gem's actual source code
9494
log # RVM will create a log folder when running commands across multiple ruby versions.
9595
pkg # Created when the gem is built, contains built versions of the gem
96-
spec # Source directory for the RSpec testing specifications
96+
spec # Source directory for the RSpec testing specifications
9797
fixtures # Files used by the unit tests to mock responses from the SoftLayer network API
9898

9999
Most of the source files that implement the gem are found in `lib/softlayer`. If you wish to add new functionality, or edit existing functionality, you will probably edit the class files in this directory. Unit tests using Rspec are found in the spec folder and should generally follow the naming convention of <Class>_spec.rb

lib/softlayer/BareMetalServerOrder.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ class BareMetalServerOrder
3232
# a Bare Metal Instance
3333
#++
3434

35-
# String, short name of the data center that will house the new Bare Metal Instance (e.g. "dal05" or "sea01")
36-
# Corresponds to +datacenter.name+ in the documentation for +createObject+.
35+
# An instance of SoftLayer::Datacenter. The server will be provisioned in this data center
3736
attr_accessor :datacenter
3837

3938
# String, The hostname to assign to the new server
@@ -152,7 +151,7 @@ def hardware_instance_template
152151

153152
template["privateNetworkOnlyFlag"] = true if @private_network_only
154153

155-
template["datacenter"] = {"name" => @datacenter} if @datacenter
154+
template["datacenter"] = {"name" => @datacenter.name} if @datacenter
156155
template['userData'] = [{'value' => @user_metadata}] if @user_metadata
157156
template['networkComponents'] = [{'maxSpeed'=> @max_port_speed}] if @max_port_speed
158157
template['postInstallScriptUri'] = @provision_script_URI.to_s if @provision_script_URI
@@ -184,7 +183,7 @@ def self.create_object_options(client = nil)
184183
##
185184
# Return a list of values that are valid for the :datacenter attribute
186185
def self.datacenter_options(client = nil)
187-
create_object_options(client)["datacenters"].collect { |datacenter_spec| datacenter_spec['template']['datacenter']["name"] }.uniq.sort!
186+
create_object_options(client)["datacenters"].collect { |datacenter_spec| Datacenter.datacenter_named(datacenter_spec['template']['datacenter']['name'], client) }.uniq
188187
end
189188

190189
def self.core_options(client = nil)

lib/softlayer/BareMetalServerOrder_Package.rb

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@ module SoftLayer
2828
class BareMetalServerOrder_Package < Server
2929
# The following properties are required in a server order.
3030

31-
# The product package identifying the base configuration for the server.
32-
# a list of Bare Metal Server product packages is returned by
31+
# The product package object (an instance of SoftLayer::ProductPackage) identifying the base
32+
# configuration for the server. A list of Bare Metal Server product packages is returned by
3333
# SoftLayer::ProductPackage.bare_metal_server_packages
3434
attr_reader :package
3535

36-
# String, short name of the data center that will house the new virtual server (e.g. "dal05" or "sea01")
37-
# A list of valid data centers can be found in ProductPackage#datacenter_options
36+
# An instance of SoftLayer::Datacenter. The server will be provisioned in this data center.
37+
# The set of datacenters available is determined by the package and may be obtained from
38+
# the SoftLayer::ProductPackage object using the #datacenter_options method.
3839
attr_accessor :datacenter
3940

4041
# The hostname of the server being created (i.e. 'sldn' is the hostname of sldn.softlayer.com).
@@ -125,8 +126,7 @@ def hardware_order
125126
}
126127
}
127128

128-
product_order['location'] = @package.location_id_for_datacenter_name(@datacenter.downcase) if @datacenter
129-
129+
product_order['location'] = @datacenter.id if @datacenter
130130
product_order['sshKeys'] = [{ 'sshKeyIds' => @ssh_key_ids }] if @ssh_key_ids
131131
product_order['provisionScripts'] = [@provision_script_URI.to_s] if @provision_script_URI
132132

@@ -142,7 +142,5 @@ def hardware_order
142142

143143
product_order
144144
end
145-
146145
end # BareMetalServerOrder_Package
147-
148146
end # SoftLayer

lib/softlayer/Datacenter.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ module SoftLayer
88
##
99
# A Data Center in the SoftLayer network
1010
#
11-
# This class corresponds to the +SoftLayer_Location+ data type:
12-
#
11+
# This class corresponds to the SoftLayer_Location++ data type:
12+
#
1313
# http://sldn.softlayer.com/reference/datatypes/SoftLayer_Location
1414
#
1515
# Although in this context it is used to represent a data center and

lib/softlayer/ImageTemplate.rb

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def flex_image?
5454
##
5555
# Changes the notes on an template to be the given strings
5656
def notes=(new_notes)
57-
# it is not a typo that this sets the "note" property. The
57+
# it is not a typo that this sets the "note" property. The
5858
# property in the network api is "note", the model exposes it as
5959
# 'notes' for self-consistency
6060
self.service.editObject({ "note" => new_notes.to_s})
@@ -67,11 +67,11 @@ def tags
6767
end
6868

6969
##
70-
# Sets the tags on the template. Note: a pre-existing tag will be
70+
# Sets the tags on the template. Note: a pre-existing tag will be
7171
# removed from the template if it does not appear in the array given.
7272
# The list of tags must be comprehensive.
7373
def tags=(tags_array)
74-
as_strings = tags_array.collect { |tag| tag.to_s }
74+
as_strings = tags_array.collect { |tag| tag.to_s }
7575
self.service.setTags(as_strings.join(','))
7676
end
7777

@@ -83,7 +83,7 @@ def datacenters
8383

8484
##
8585
# Accepts an array of datacenters (instances of SoftLayer::Datacenter) where this
86-
# image should be made available. The call will kick off one or more transactions
86+
# image should be made available. The call will kick off one or more transactions
8787
# to make the image available in the given datacenters. These transactions can take
8888
# some time to complete.
8989
#
@@ -99,10 +99,10 @@ def datacenters=(datacenters_array)
9999

100100
self.service.setAvailableLocations(datacenter_data.compact)
101101
end
102-
102+
103103
##
104104
# Returns an array of the datacenters that this image can be stored in.
105-
# This is the set of datacenters that you may choose from, when putting
105+
# This is the set of datacenters that you may choose from, when putting
106106
# together a list you will send to the datacenters= setter.
107107
#
108108
def available_datacenters
@@ -118,7 +118,7 @@ def shared_with_accounts
118118
accounts_data = self.service.getAccountReferences
119119
accounts_data.collect { |account_data| account_data["accountId"] }
120120
end
121-
121+
122122
##
123123
# Change the set of accounts that this image is shared with.
124124
# The parameter is an array of account ID's.
@@ -136,7 +136,7 @@ def shared_with_accounts= (account_id_list)
136136
# with the account that owns it, however, this leads to a rather odd state
137137
# where the image has allocated resources (that the account may be charged for)
138138
# but no way to delete those resources. For that reason this model
139-
# always includes the account ID that owns the image in the list of
139+
# always includes the account ID that owns the image in the list of
140140
# accounts the image will be shared with.
141141
my_account_id = self['accountId']
142142
accounts_to_add.push(my_account_id) if !already_sharing_with.include?(my_account_id) && !accounts_to_add.include?(my_account_id)
@@ -158,9 +158,9 @@ def shared_with_accounts= (account_id_list)
158158
def delete!
159159
self.service.deleteObject
160160
end
161-
161+
162162
##
163-
# Repeatedly poll the netwokr API until transactions related to this image
163+
# Repeatedly poll the netwokr API until transactions related to this image
164164
# template are finished
165165
#
166166
# A template is not 'ready' until all the transactions on the template
@@ -179,7 +179,7 @@ def wait_until_ready(max_trials, seconds_between_tries = 2)
179179
parent_ready = !(has_sl_property? :transactionId) || (self[:transactionId] == "")
180180
children_ready = (nil == self["children"].find { |child| child["transactionId"] != "" })
181181

182-
ready = parent_ready && children_ready
182+
ready = parent_ready && children_ready
183183
yield ready if block_given?
184184

185185
num_trials = num_trials + 1
@@ -188,12 +188,12 @@ def wait_until_ready(max_trials, seconds_between_tries = 2)
188188

189189
ready
190190
end
191-
191+
192192
# ModelBase protocol methods
193193
def service
194194
softlayer_client['Virtual_Guest_Block_Device_Template_Group'].object_with_id(self.id)
195195
end
196-
196+
197197
def softlayer_properties(object_mask = nil)
198198
self.service.object_mask(self.class.default_object_mask).getObject
199199
end
@@ -342,7 +342,7 @@ def self.find_public_templates(options_hash = {})
342342
# If no client can be found the routine will raise an error.
343343
#
344344
# The options may include the following keys
345-
# * <b>+:object_mask+</b> (string) - A object mask of properties, in addition to the default properties, that you wish to retrieve for the server
345+
# * <b>+:object_mask+</b> (string) - A object mask of properties, in addition to the default properties, that you wish to retrieve for the template
346346
def self.template_with_id(id, options_hash = {})
347347
softlayer_client = options_hash[:client] || Client.default_client
348348
raise "#{__method__} requires a client but none was given and Client::default_client is not set" if !softlayer_client
@@ -358,10 +358,27 @@ def self.template_with_id(id, options_hash = {})
358358
new(softlayer_client, template_data)
359359
end
360360

361+
##
362+
# Retrieve the image template with the given global ID
363+
#
364+
# The options parameter should contain:
365+
#
366+
# <b>+:client+</b> - The client used to connect to the API
367+
#
368+
# If no client is given, then the routine will try to use Client.default_client
369+
# If no client can be found the routine will raise an error.
370+
#
371+
# The options may include the following keys
372+
# * <b>+:object_mask+</b> (string) - A object mask of properties, in addition to the default properties, that you wish to retrieve for the template
373+
def self.template_with_global_id(global_id, options_hash = {})
374+
templates = find_public_templates(options_hash.merge(:global_id => global_id))
375+
templates.empty? ? nil : templates[0]
376+
end
377+
361378
protected
362379

363380
def self.default_object_mask
364381
return "mask[id,accountId,name,note,globalIdentifier,datacenters,blockDevices,tagReferences,publicFlag,flexImageFlag,transactionId,children.transactionId]"
365382
end
366-
end
383+
end
367384
end

lib/softlayer/ModelBase.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def to_ary()
116116
#
117117
def softlayer_properties(object_mask = nil)
118118
raise "Abstract method softlayer_properties in ModelBase was called"
119-
end
119+
end
120120

121121
##
122122
# The softlayer_hash stores the low-level information about an

lib/softlayer/ProductPackage.rb

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class ProductPackage < ModelBase
4545

4646
##
4747
# The list of locations where this product package is available.
48-
sl_attr :availableLocations
48+
sl_attr :available_locations, 'availableLocations'
4949

5050
##
5151
# The set of product categories needed to make an order for this product package.
@@ -105,15 +105,7 @@ def category(category_code)
105105
end
106106

107107
def datacenter_options
108-
availableLocations.collect { |location_data| location_data["location"]["name"] }
109-
end
110-
111-
##
112-
# Given a datacenter name that was returned by datacenter_options, use information
113-
# in the package to retrieve a location id.
114-
def location_id_for_datacenter_name(datacenter_name)
115-
location_data = availableLocations.find { |location_data| location_data["location"]["name"] == datacenter_name }
116-
location_data["locationId"]
108+
available_locations.collect { |location_data| Datacenter::datacenter_named(location_data["location"]["name"], self.softlayer_client) }.compact
117109
end
118110

119111
def service

lib/softlayer/VirtualServer.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ def upgrade_max_port_speed!(network_speed_in_Mbps)
131131
#
132132
# The routine returns the instance of SoftLayer::ImageTemplate that is
133133
# created. That image template will probably not be available immediately, however.
134-
# You may use the wait_until_ready routine of SoftLayer::ImageTemplate to
134+
# You may use the wait_until_ready routine of SoftLayer::ImageTemplate to
135135
# wait on it.
136136
#
137137
def capture_image(image_name, include_attached_storage = false, image_notes = nil)
@@ -141,7 +141,7 @@ def capture_image(image_name, include_attached_storage = false, image_notes = ni
141141
disks = self.blockDevices.select(&disk_filter)
142142

143143
self.service.createArchiveTransaction(image_name, disks, notes ? notes : "") if disks && !disks.empty?
144-
144+
145145
image_templates = SoftLayer::ImageTemplate.find_private_templates(:name => image_name)
146146
image_templates[0] if !image_templates.empty?
147147
end

lib/softlayer/VirtualServerOrder.rb

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ class VirtualServerOrder
2424
# a virtual server
2525
#++
2626

27-
# String, short name of the data center that will house the new virtual server (e.g. "dal05" or "sea01")
28-
# Corresponds to +datacenter.name+ in the documentation for createObject. If not provided, the server will
29-
# be provisioned in the first available data center.
27+
# An instance of SoftLayer::Datacenter. The server will be provisioned in that Datacenter.
3028
attr_accessor :datacenter
3129

3230
# String, The hostname to assign to the new server
@@ -44,17 +42,18 @@ class VirtualServerOrder
4442
attr_accessor :memory
4543

4644
#--
47-
# These two options are mutually exclusive, but one or the other must be provided.
48-
# If you provide both, the image_global_id will be added to the order and the os_reference_code will be ignored
45+
# These two options are mutually exclusive, but one of them must be provided.
46+
# If you provide both, the image_template will be added to the order and the
47+
# os_reference_code will be ignored
4948
#++
5049

5150
# String, An OS reference code for the operating system to install on the virtual server
5251
# Corresponds to +operatingSystemReferenceCode+ in the +createObject+ documentation
5352
attr_accessor :os_reference_code
5453

55-
# String, The globalIdentifier of a disk image to put on the newly created server
56-
# Corresponds to +blockDeviceTemplateGroup.globalIdentifier+ in the +createObject+ documentation
57-
attr_accessor :image_global_id
54+
# An instance of the SoftLayer::ImageTemplate class. Represents the image template that should
55+
# be installed on the server.
56+
attr_accessor :image_template
5857

5958
#--
6059
# Optional attributes
@@ -159,16 +158,16 @@ def virtual_guest_template
159158
template["dedicatedAccountHostOnlyFlag"] = true if @dedicated_host_only
160159
template["privateNetworkOnlyFlag"] = true if @private_network_only
161160

162-
template["datacenter"] = {"name" => @datacenter} if @datacenter
161+
template["datacenter"] = {"name" => @datacenter.name} if @datacenter
163162
template['userData'] = [{'value' => @user_metadata}] if @user_metadata
164163
template['networkComponents'] = [{'maxSpeed'=> @max_port_speed}] if @max_port_speed
165164
template['postInstallScriptUri'] = @provision_script_URI.to_s if @provision_script_URI
166165
template['sshKeys'] = @ssh_key_ids.collect { |ssh_key_id| {'id'=> ssh_key_id.to_i } } if @ssh_key_ids
167166
template['primaryNetworkComponent'] = { "networkVlan" => { "id" => @public_vlan_id.to_i } } if @public_vlan_id
168167
template["primaryBackendNetworkComponent"] = { "networkVlan" => {"id" => @private_vlan_id.to_i } } if @private_vlan_id
169168

170-
if @image_global_id
171-
template["blockDeviceTemplateGroup"] = {"globalIdentifier" => @image_global_id}
169+
if @image_template
170+
template["blockDeviceTemplateGroup"] = {"globalIdentifier" => @image_template.global_id}
172171
elsif @os_reference_code
173172
template["operatingSystemReferenceCode"] = @os_reference_code
174173
end
@@ -213,7 +212,7 @@ def self.create_object_options(client = nil)
213212
##
214213
# Return a list of values that are valid for the :datacenter attribute
215214
def self.datacenter_options(client = nil)
216-
create_object_options(client)["datacenters"].collect { |datacenter_spec| datacenter_spec['template']['datacenter']["name"] }.uniq.sort!
215+
create_object_options(client)["datacenters"].collect { |datacenter_spec| Datacenter.datacenter_named(datacenter_spec['template']['datacenter']['name'], client) }.uniq
217216
end
218217

219218
##

0 commit comments

Comments
 (0)