Skip to content

Commit 141865b

Browse files
committed
Pull remote changes into the local branch to complete merging 2.2.2 into 3.0 branch
2 parents da9d2cd + 028df3a commit 141865b

43 files changed

Lines changed: 1402 additions & 268 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.textile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
*3.0*
22
* 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.
3-
* 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
3+
* Added a model for Virtual Server Image Templates (SoftLayer::ImageTemplate) - VirtualServerOrder now requires an instance of this class rather than allowing you to provide the global_id of an image
44
* 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.
55
* Virtual Server Upgrades are now handled by the VirtualServerUpgradeOrder class and not the VirtualServer class. This change was made for several reasons. Firt and foremost, it allows multiple aspects of a virtual server to be upgraded at once without having to wait on separate transactions to complete between upgrades. Secondly it opens the door for additional upgrades (for example, to disk configuration) to be added in the future.
66
* Added a method to reboot servers.
77
* The routine to retreive the open tickets on an account has been moved from the Ticket class. The set of open tickets is now a dynamic property of an account object.
8+
* The Model Layer now includes models for Server (aka. Shared) and VLAN (aka. Dedicated) firewalls in the ServerFirewall, and VLANFireall classes respectively. There are corresponding classes for ordering firewalls (ServerFirewallOrder and VLANFirewallOrder). To facilitate the process of locating the 'id' for a firewall, the Account class includes the find_VLAN_with_number routine which lets you look up the segments of a firewall from the VLAN nubmer.
89

910
*2.2.2*
1011
* Fixed a bug in BareMetalServerOrder_Package.rb where the order template did not use an array for the "hardware" key. This lead to an order template that would be accepted by verifyOrder, but rejected by placeOrder. An internal issue to review verifyOrder has also been generated. (reported by Rohit Singh)

examples/order_bare_metal_package.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,11 @@ def tl_dr_version
129129
# We have a configuration for the server, we also need a location for the new server.
130130
# The package can give us a list of locations. Let's print out that list
131131
puts "\nData Centers for '#{quad_intel_package.name}':"
132-
quad_intel_package.datacenter_options.each { |location| puts "\t#{location}"}
132+
quad_intel_package.datacenter_options.each { |datacenter| puts "\t#{datacenter.name}"}
133133

134134
# With all the config options in place we can now construct the product order.
135135
server_order = SoftLayer::BareMetalServerOrder_Package.new(quad_intel_package, client)
136-
server_order.datacenter = 'sng01'
136+
server_order.datacenter = SoftLayer::Datacenter.datacenter_named 'sng01', client
137137
server_order.hostname = 'sample'
138138
server_order.domain = 'softlayerapi.org'
139139
server_order.configuration_options = config_options

examples/order_server_firewall.rb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#
2+
# Copyright (c) 2014 SoftLayer Technologies, Inc. All rights reserved.
3+
#
4+
# Permission is hereby granted, free of charge, to any person obtaining a copy
5+
# of this software and associated documentation files (the "Software"), to deal
6+
# in the Software without restriction, including without limitation the rights
7+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
# copies of the Software, and to permit persons to whom the Software is
9+
# furnished to do so, subject to the following conditions:
10+
#
11+
# The above copyright notice and this permission notice shall be included in
12+
# all copies or substantial portions of the Software.
13+
#
14+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
# THE SOFTWARE.
21+
#
22+
23+
require 'rubygems'
24+
require 'softlayer_api'
25+
require 'pp'
26+
27+
# This is the id of the server you want to protect with a firewall.
28+
# The server can be Bare Metal or Virtual. It should have a public
29+
# network interface, and it should not already have a firewall on it.
30+
server_id = 257696 # 12345
31+
32+
# In this example, we assume this is a Bare Metal Server
33+
is_virtual_server = false
34+
35+
# Work with the SoftLayer API begins with a client. By setting
36+
# the "default" client we avoid having to specify the client repeatedly
37+
# in calls that follow.
38+
SoftLayer::Client.default_client = SoftLayer::Client.new(
39+
# :username => "joecustomer" # enter your username here
40+
# :api_key => "feeddeadbeefbadf00d..." # enter your api key here
41+
)
42+
43+
# in this case we go straight to the appropriate class to find the server
44+
# an alternative might be to create the account for this client and
45+
# search the list of servers for the one with the appropriate ID.
46+
if is_virtual_server
47+
server = SoftLayer::VirtualServer.server_with_id(server_id)
48+
else
49+
server = SoftLayer::BareMetalServer.server_with_id(server_id)
50+
end
51+
52+
# Create an instance of SoftLayer::ServerFirewallOrder
53+
order = SoftLayer::ServerFirewallOrder.new(server)
54+
55+
begin
56+
# this example calls order.verify which will build the order, submit it
57+
# to the network API, and will throw an exception if the order is
58+
# invalid.
59+
order.verify()
60+
puts "Firewall order is good for #{server.fullyQualifiedDomainName}"
61+
rescue => exception
62+
puts "Firewall order failed for #{server.fullyQualifiedDomainName} because #{exception}"
63+
end

lib/softlayer/APIParameterFilter.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ def initialize(target, starting_parameters = nil)
4343
@parameters = starting_parameters || {}
4444
end
4545

46+
##
47+
# API Parameter filters will call through to a particular service
48+
# but that service is defined by their target
49+
def service_name
50+
return @target.service_name
51+
end
52+
4653
##
4754
# Adds an API filter that narrows the scope of a call to an object with
4855
# a particular ID. For example, if you want to get the ticket
@@ -173,7 +180,7 @@ def server_result_offset
173180
##
174181
# A utility method that returns the object filter (if any) stored with this filter.
175182
def server_object_filter
176-
self.parameters[:object_filter].to_h
183+
self.parameters[:object_filter].to_h if self.parameters.has_key?(:object_filter)
177184
end
178185

179186
##

lib/softlayer/Account.rb

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,25 @@ class Account < SoftLayer::ModelBase
123123
end
124124

125125
def service
126-
softlayer_client["Account"].object_with_id(self.id)
126+
softlayer_client[:Account].object_with_id(self.id)
127+
end
128+
129+
##
130+
# Searches the account's list of VLANs for the ones with the given
131+
# vlan number. This may return multiple results because a VLAN can
132+
# span different routers and you will get a separate segment for
133+
# each router.
134+
#
135+
# The IDs of the different segments can be helpful for ordering
136+
# firewalls.
137+
#
138+
def find_VLAN_with_number(vlan_number)
139+
filter = SoftLayer::ObjectFilter.new() { |filter|
140+
filter.accept('networkVlans.vlanNumber').when_it is vlan_number
141+
}
142+
143+
vlan_data = self.service.object_mask("mask[id,vlanNumber,primaryRouter,networkSpace]").object_filter(filter).getNetworkVlans
144+
return vlan_data
127145
end
128146

129147
##
@@ -134,7 +152,7 @@ def self.account_for_client(client = nil)
134152
softlayer_client = client || Client.default_client
135153
raise "#{__method__} requires a client but none was given and Client::default_client is not set" if !softlayer_client
136154

137-
account_service = softlayer_client['Account']
155+
account_service = softlayer_client[:Account]
138156
network_hash = account_service.getObject()
139157
new(softlayer_client, network_hash)
140158
end

lib/softlayer/BareMetalServer.rb

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class BareMetalServer < Server
2727
#
2828
def bare_metal_instance?
2929
if has_sl_property?(:bareMetalInstanceFlag)
30-
self["bareMetalInstanceFlag"] != 0
30+
self['bareMetalInstanceFlag'] != 0
3131
else
3232
false
3333
end
@@ -47,19 +47,20 @@ def cancel!(reason = :unneeded, comment = '')
4747
if !bare_metal_instance? then
4848
cancellation_reasons = self.class.cancellation_reasons()
4949
cancel_reason = cancellation_reasons[reason] || cancellation_reasons[:unneeded]
50-
softlayer_client["Ticket"].createCancelServerTicket(self.id, cancel_reason, comment, true, 'HARDWARE')
50+
softlayer_client[:Ticket].createCancelServerTicket(self.id, cancel_reason, comment, true, 'HARDWARE')
5151
else
5252
# 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.billingItem['id'].to_i).cancelService()
5454
end
5555
end
5656

5757
##
58-
# Returns the SoftLayer Service used to work with this Server
58+
# Returns the typical Service used to work with this Server
5959
# For Bare Metal Servers that is +SoftLayer_Hardware+ though in some special cases
60-
# you may have to use +SoftLayer_Hardware_Server+ as a type or service.
60+
# you may have to use +SoftLayer_Hardware_Server+ as a type or service. That
61+
# service object is available thorugh the hardware_server_service method
6162
def service
62-
return softlayer_client["Hardware"].object_with_id(self.id)
63+
return softlayer_client[:Hardware_Server].object_with_id(self.id)
6364
end
6465

6566
##
@@ -106,6 +107,36 @@ def self.cancellation_reasons
106107
}
107108
end
108109

110+
##
111+
# Returns the max port speed of the public network interfaces of the server taking into account
112+
# bound interface pairs (redundant network cards).
113+
def firewall_port_speed
114+
network_components = self.service.object_mask("mask[id,maxSpeed,networkComponentGroup.networkComponents]").getFrontendNetworkComponents()
115+
116+
# Split the interfaces into grouped and ungrouped interfaces. The max speed of a group will be the sum
117+
# of the individual speeds in that group. The max speed of ungrouped interfaces is simply the max speed
118+
# of that interface.
119+
grouped_interfaces, ungrouped_interfaces = network_components.partition{ |interface| interface.has_key?("networkComponentGroup") }
120+
121+
if !grouped_interfaces.empty?
122+
group_speeds = grouped_interfaces.collect do |interface|
123+
interface['networkComponentGroup']['networkComponents'].inject(0) {|total_speed, component| total_speed += component['maxSpeed']}
124+
end
125+
126+
max_group_speed = group_speeds.max
127+
else
128+
max_group_speed = 0
129+
end
130+
131+
if !ungrouped_interfaces.empty?
132+
max_ungrouped_speed = ungrouped_interfaces.collect { |interface| interface['maxSpeed']}.max
133+
else
134+
max_ungrouped_speed = 0
135+
end
136+
137+
return [max_group_speed, max_ungrouped_speed].max
138+
end
139+
109140
##
110141
# Retrive the bare metal server with the given server ID from the
111142
# SoftLayer API
@@ -120,7 +151,7 @@ def self.server_with_id(server_id, options = {})
120151
softlayer_client = options[:client] || Client.default_client
121152
raise "#{__method__} requires a client but none was given and Client::default_client is not set" if !softlayer_client
122153

123-
hardware_service = softlayer_client["Hardware"]
154+
hardware_service = softlayer_client[:Hardware_Server]
124155
hardware_service = hardware_service.object_mask(default_object_mask.to_sl_object_mask)
125156

126157
if options.has_key?(:object_mask)
@@ -199,7 +230,7 @@ def self.find_servers(options_hash = {})
199230
} );
200231
end
201232

202-
account_service = softlayer_client['Account']
233+
account_service = softlayer_client[:Account]
203234
account_service = account_service.object_filter(object_filter) unless object_filter.empty?
204235
account_service = account_service.object_mask(default_object_mask.to_sl_object_mask)
205236

lib/softlayer/BareMetalServerOrder.rb

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def verify()
111111
order_template = hardware_instance_template
112112
order_template = yield order_template if block_given?
113113

114-
@softlayer_client["Hardware"].generateOrderTemplate(order_template)
114+
@softlayer_client[:Hardware].generateOrderTemplate(order_template)
115115
end
116116

117117
##
@@ -124,8 +124,8 @@ def place_order!()
124124
order_template = hardware_instance_template
125125
order_template = yield order_template if block_given?
126126

127-
server_hash = @softlayer_client["Hardware"].createObject(order_template)
128-
SoftLayer::BareMetalServer.server_with_id(server_hash["id"], :client => @softlayer_client) if server_hash
127+
server_hash = @softlayer_client[:Hardware].createObject(order_template)
128+
SoftLayer::BareMetalServer.server_with_id(server_hash['id'], :client => @softlayer_client) if server_hash
129129
end
130130

131131
protected
@@ -147,15 +147,15 @@ def hardware_instance_template
147147
"hourlyBillingFlag" => !!@hourly
148148
}
149149

150-
template["privateNetworkOnlyFlag"] = true if @private_network_only
150+
template['privateNetworkOnlyFlag'] = true if @private_network_only
151151

152-
template["datacenter"] = {"name" => @datacenter.name} if @datacenter
152+
template['datacenter'] = {"name" => @datacenter.name} if @datacenter
153153
template['userData'] = [{'value' => @user_metadata}] if @user_metadata
154154
template['networkComponents'] = [{'maxSpeed'=> @max_port_speed}] if @max_port_speed
155155
template['postInstallScriptUri'] = @provision_script_URI.to_s if @provision_script_URI
156156
template['sshKeys'] = @ssh_key_ids.collect { |ssh_key| {'id'=> ssh_key.to_i } } if @ssh_key_ids
157157
template['primaryNetworkComponent'] = { "networkVlan" => { "id" => @public_vlan_id.to_i } } if @public_vlan_id
158-
template["primaryBackendNetworkComponent"] = { "networkVlan" => {"id" => @private_vlan_id.to_i } } if @private_vlan_id
158+
template['primaryBackendNetworkComponent'] = { "networkVlan" => {"id" => @private_vlan_id.to_i } } if @private_vlan_id
159159

160160
if @disks && !@disks.empty?
161161
template['hardDrives'] = @disks.collect do |disk|
@@ -174,36 +174,36 @@ def self.create_object_options(client = nil)
174174
raise "#{__method__} requires a client but none was given and Client::default_client is not set" if !softlayer_client
175175

176176
@@create_object_options ||= nil
177-
@@create_object_options = softlayer_client["Hardware"].getCreateObjectOptions() if !@@create_object_options
177+
@@create_object_options = softlayer_client[:Hardware].getCreateObjectOptions() if !@@create_object_options
178178
@@create_object_options
179179
end
180180

181181
##
182182
# Return a list of values that are valid for the :datacenter attribute
183183
def self.datacenter_options(client = nil)
184-
create_object_options(client)["datacenters"].collect { |datacenter_spec| Datacenter.datacenter_named(datacenter_spec['template']['datacenter']['name'], client) }.uniq
184+
create_object_options(client)['datacenters'].collect { |datacenter_spec| Datacenter.datacenter_named(datacenter_spec['template']['datacenter']['name'], client) }.uniq
185185
end
186186

187187
def self.core_options(client = nil)
188-
create_object_options(client)["processors"].collect { |processor_spec| processor_spec['template']['processorCoreAmount'] }.uniq.sort!
188+
create_object_options(client)['processors'].collect { |processor_spec| processor_spec['template']['processorCoreAmount'] }.uniq.sort!
189189
end
190190

191191
##
192192
# Return a list of values that are valid the array given to the :disks
193193
def self.disk_options(client = nil)
194-
create_object_options(client)["hardDrives"].collect { |disk_spec| disk_spec['template']['hardDrives'][0]['capacity'].to_i}.uniq.sort!
194+
create_object_options(client)['hardDrives'].collect { |disk_spec| disk_spec['template']['hardDrives'][0]['capacity'].to_i}.uniq.sort!
195195
end
196196

197197
##
198198
# Returns a list of the valid :os_refrence_codes
199199
def self.os_reference_code_options(client = nil)
200-
create_object_options(client)["operatingSystems"].collect { |os_spec| os_spec['template']['operatingSystemReferenceCode'] }.uniq.sort!
200+
create_object_options(client)['operatingSystems'].collect { |os_spec| os_spec['template']['operatingSystemReferenceCode'] }.uniq.sort!
201201
end
202202

203203
##
204204
# Returns a list of the :max_port_speeds
205205
def self.max_port_speed_options(client = nil)
206-
create_object_options(client)["networkComponents"].collect { |component_spec| component_spec['template']['networkComponents'][0]['maxSpeed'] }
206+
create_object_options(client)['networkComponents'].collect { |component_spec| component_spec['template']['networkComponents'][0]['maxSpeed'] }
207207
end
208208

209209
end # class BareMetalServerOrder

lib/softlayer/BareMetalServerOrder_Package.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class BareMetalServerOrder_Package < Server
5858

5959
# An array of the ids of SSH keys to install on the server upon provisioning
6060
# To obtain a list of existing SSH keys, call getSshKeys on the SoftLayer_Account service:
61-
# client['Account'].getSshKeys()
61+
# client[:Account].getSshKeys()
6262
attr_accessor :ssh_key_ids
6363

6464
# The URI of a script to execute on the server after it has been provisioned. This may be
@@ -88,7 +88,7 @@ def initialize(package, client = nil)
8888
def verify
8989
product_order = hardware_order
9090
product_order = yield product_order if block_given?
91-
softlayer_client["Product_Order"].verifyOrder(product_order)
91+
softlayer_client[:Product_Order].verifyOrder(product_order)
9292
end
9393

9494
##
@@ -106,7 +106,7 @@ def verify
106106
def place_order!
107107
product_order = hardware_order
108108
product_order = yield product_order if block_given?
109-
softlayer_client["Product_Order"].placeOrder(product_order)
109+
softlayer_client[:Product_Order].placeOrder(product_order)
110110
end
111111

112112
protected

lib/softlayer/Client.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class Client
3232

3333
# A string passsed as the value for the User-Agent header when requests are sent to SoftLayer API.
3434
attr_accessor :user_agent
35-
35+
3636
# An integer value (in seconds). The number of seconds to wait for HTTP requests to the network API
3737
# until they timeout. This value can be nil in which case the timeout will be the default value for
3838
# the library handling network communication (often 30 seconds)
@@ -84,8 +84,10 @@ def initialize(options = {})
8484
# and the endpoint url
8585
@endpoint_url = settings[:endpoint_url] || API_PUBLIC_ENDPOINT
8686

87+
# set the user agent to the one provided, or set it to a default one
8788
@user_agent = settings[:user_agent] || "softlayer_api gem/#{SoftLayer::VERSION} (Ruby #{RUBY_PLATFORM}/#{RUBY_VERSION})"
88-
89+
90+
# and assign a time out if the settings offer one
8991
@network_timeout = settings[:timeout] if settings.has_key?(:timeout)
9092

9193
raise "A SoftLayer Client requires a username" if !@username || @username.empty?

lib/softlayer/Config.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ def Config.globals_settings
7272

7373
def Config.environment_settings
7474
result = {}
75-
result[:username] = ENV["SL_USERNAME"] if ENV["SL_USERNAME"]
76-
result[:api_key] = ENV["SL_API_KEY"] if ENV["SL_API_KEY"]
75+
result[:username] = ENV['SL_USERNAME'] if ENV['SL_USERNAME']
76+
result[:api_key] = ENV['SL_API_KEY'] if ENV['SL_API_KEY']
7777
result
7878
end
7979

@@ -89,7 +89,7 @@ def Config.file_settings(*additional_files)
8989
search_path.each do |file_path|
9090
if File.readable? file_path
9191
config = ConfigParser.new file_path
92-
softlayer_section = config["softlayer"]
92+
softlayer_section = config['softlayer']
9393

9494
if softlayer_section
9595
result[:username] = softlayer_section['username'] if softlayer_section['username']

0 commit comments

Comments
 (0)