softlayer_api 3.0.b1 → 3.0.b2

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.
@@ -47,7 +47,7 @@ module SoftLayer
47
47
  # a particular entity in the SoftLayer_Ticket service. The particular
48
48
  # entity is identified by its id so the Ticket class would return
49
49
  #
50
- # softlayer_client["Ticket"].object_with_id
50
+ # softlayer_client[:Ticket].object_with_id
51
51
  #
52
52
  # which is a service which would allow calls to the ticket service
53
53
  # through that particular object.
@@ -0,0 +1,14 @@
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
+ class NetworkComponent < SoftLayer::ModelBase
9
+ sl_attr :name
10
+ sl_attr :port
11
+ sl_attr :speed
12
+ sl_attr :maxSpeed
13
+ end
14
+ end
@@ -10,9 +10,23 @@ module SoftLayer
10
10
  # the product order is the price_id, the rest of the information is provided
11
11
  # to make the object friendly to humans who may be searching for the
12
12
  # meaning of a given price_id.
13
- class ProductConfigurationOption < Struct.new(:price_id, :description, :capacity, :units, :setupFee, :laborFee, :oneTimeFee, :recurringFee, :hourlyRecurringFee)
13
+ class ProductConfigurationOption < Struct.new(:price_id, :description, :capacity, :units, :setupFee, :laborFee,
14
+ :oneTimeFee, :recurringFee, :hourlyRecurringFee)
14
15
  # Is it evil, or just incongruous to give methods to a struct?
15
16
 
17
+ def initialize(package_item_data, price_item_data)
18
+ self.description = package_item_data['description']
19
+ self.capacity = package_item_data['capacity']
20
+ self.units = package_item_data['units']
21
+
22
+ self.price_id = price_item_data['id']
23
+ self.setupFee = price_item_data['setupFee'] ? price_item_data['setupFee'].to_f : 0.0
24
+ self.laborFee = price_item_data['laborFee'] ? price_item_data['laborFee'].to_f : 0.0
25
+ self.oneTimeFee = price_item_data['oneTimeFee'] ? price_item_data['oneTimeFee'].to_f : 0.0
26
+ self.recurringFee = price_item_data['recurringFee'] ? price_item_data['recurringFee'].to_f : 0.0
27
+ self.hourlyRecurringFee = price_item_data['hourlyRecurringFee'] ? price_item_data['hourlyRecurringFee'].to_f : 0.0
28
+ end
29
+
16
30
  # returns true if the configurtion option has no fees associated with it.
17
31
  def free?
18
32
  self.setupFee == 0 && self.laborFee == 0 && self.oneTimeFee == 0 && self.recurringFee == 0 && self.hourlyRecurringFee == 0
@@ -63,24 +77,14 @@ module SoftLayer
63
77
  # web UI), but this code collapses the groups.
64
78
  self['groups'].collect do |group|
65
79
  group['prices'].sort{|lhs,rhs| lhs['sort'] <=> rhs['sort']}.collect do |price_item|
66
- ProductConfigurationOption.new(
67
- price_item['id'],
68
- price_item['item']['description'],
69
- price_item['item']['capacity'],
70
- price_item['item']['units'],
71
- price_item['setupFee'] ? price_item['setupFee'].to_f : 0.0,
72
- price_item['laborFee'] ? price_item['laborFee'].to_f : 0.0,
73
- price_item['oneTimeFee'] ? price_item['oneTimeFee'].to_f : 0.0,
74
- price_item['recurringFee'] ? price_item['recurringFee'].to_f : 0.0,
75
- price_item['hourlyRecurringFee'] ? price_item['hourlyRecurringFee'].to_f : 0.0
76
- )
80
+ ProductConfigurationOption.new(price_item['item'], price_item)
77
81
  end
78
82
  end.flatten # flatten out the individual group arrays.
79
83
  end
80
84
  end
81
85
 
82
86
  def service
83
- softlayer_client["SoftLayer_Product_Item_Category"].object_with_id(self.id)
87
+ softlayer_client[:SoftLayer_Product_Item_Category].object_with_id(self.id)
84
88
  end
85
89
 
86
90
  ##
@@ -65,7 +65,7 @@ module SoftLayer
65
65
  # filtering mechanism on the server side to give us a list of the categories, groups, and prices that are valid for the current
66
66
  # account at the current time. We construct the ProductItemCategory objects from the results we get back.
67
67
  #
68
- configuration_data = softlayer_client['Product_Package'].object_with_id(self.id).object_mask("mask[isRequired,itemCategory.categoryCode]").getConfiguration()
68
+ configuration_data = softlayer_client[:Product_Package].object_with_id(self.id).object_mask("mask[isRequired,itemCategory.categoryCode]").getConfiguration()
69
69
 
70
70
  # We sort of invert the information and create a map from category codes to a boolean representing
71
71
  # whether or not they are required.
@@ -75,39 +75,82 @@ module SoftLayer
75
75
  end
76
76
 
77
77
  # This call to getCategories is the one that does lots of fancy back-end filtering for us
78
- categories_data = softlayer_client['Product_Package'].object_with_id(self.id).getCategories()
78
+ categories_data = softlayer_client[:Product_Package].object_with_id(self.id).getCategories()
79
79
 
80
80
  # Run though the categories and for each one that's in our config, create a SoftLayer::ProductItemCategory object.
81
81
  # Conveniently the +keys+ of the required_by_category_code gives us a list of the category codes in the configuration
82
82
  config_categories = required_by_category_code.keys
83
- categories_data.collect do |category_data|
83
+
84
+ # collect all the categories into an array
85
+ @categories = categories_data.collect do |category_data|
84
86
  if config_categories.include? category_data['categoryCode']
85
87
  SoftLayer::ProductItemCategory.new(softlayer_client, category_data, required_by_category_code[category_data['categoryCode']])
86
88
  else
87
- nil
89
+ SoftLayer::ProductItemCategory.new(softlayer_client, category_data, false)
88
90
  end
89
91
  end.compact
92
+
93
+ # The configuration consists of only those categories that are required.
94
+ @categories.select { |category| category.required? }
95
+ end # to_update
96
+ end # configuration
97
+
98
+ ##
99
+ # The full set of product categories contained in the package
100
+ #
101
+ sl_dynamic_attr :categories do |resource|
102
+ resource.should_update? do
103
+ @categories == nil
104
+ end
105
+
106
+ resource.to_update do
107
+ # This is a bit ugly, but what we do is ask for the configuration
108
+ # which updates all the categories for the package (and marks those
109
+ # that are required)
110
+ self.configuration
111
+
112
+ # return the value constructed by the configuraiton
113
+ @categories
90
114
  end
91
115
  end
92
116
 
93
117
  ##
94
118
  # Returns an array of the required categories in this package
95
119
  def required_categories
96
- configuration.select { |category| category.required? }
120
+ configuration
97
121
  end
98
122
 
99
123
  ##
100
124
  # Returns the product category with the given category code (or nil if one cannot be found)
101
125
  def category(category_code)
102
- configuration.find { |category| category.categoryCode == category_code }
126
+ categories.find { |category| category.categoryCode == category_code }
103
127
  end
104
128
 
129
+ ##
130
+ # Returns a list of the datacenters that this package is available in
105
131
  def datacenter_options
106
- available_locations.collect { |location_data| Datacenter::datacenter_named(location_data["location"]["name"], self.softlayer_client) }.compact
132
+ available_locations.collect { |location_data| Datacenter::datacenter_named(location_data['location']['name'], self.softlayer_client) }.compact
107
133
  end
108
134
 
135
+ ##
136
+ # Returns the package items with the given description
137
+ # Currently this is returning the low-level hash representation directly from the Network API
138
+ #
139
+ def items_with_description(expected_description)
140
+ filter = ObjectFilter.new { |filter| filter.accept("items.description").when_it is(expected_description) }
141
+ items_data = self.service.object_filter(filter).getItems()
142
+
143
+ items_data.collect do |item_data|
144
+ first_price = item_data['prices'][0]
145
+ ProductConfigurationOption.new(item_data, first_price)
146
+ end
147
+ end
148
+
149
+ ##
150
+ # Returns the service for interacting with this package through the network API
151
+ #
109
152
  def service
110
- softlayer_client['Product_Package'].object_with_id(self.id)
153
+ softlayer_client[:Product_Package].object_with_id(self.id)
111
154
  end
112
155
 
113
156
  ##
@@ -122,7 +165,7 @@ module SoftLayer
122
165
  filter.accept('type.keyName').when_it is(key_name)
123
166
  end
124
167
 
125
- filtered_service = softlayer_client['Product_Package'].object_filter(filter).object_mask(self.default_object_mask('mask'))
168
+ filtered_service = softlayer_client[:Product_Package].object_filter(filter).object_mask(self.default_object_mask('mask'))
126
169
  packages_data = filtered_service.getAllObjects
127
170
  packages_data.collect { |package_data| ProductPackage.new(softlayer_client, package_data) }
128
171
  end
@@ -135,7 +178,7 @@ module SoftLayer
135
178
  softlayer_client = client || Client.default_client
136
179
  raise "#{__method__} requires a client but none was given and Client::default_client is not set" if !softlayer_client
137
180
 
138
- package_data = softlayer_client['Product_Package'].object_with_id(package_id).object_mask(self.default_object_mask('mask')).getObject
181
+ package_data = softlayer_client[:Product_Package].object_with_id(package_id).object_mask(self.default_object_mask('mask')).getObject
139
182
  ProductPackage.new(softlayer_client, package_data)
140
183
  end
141
184
 
@@ -168,6 +211,13 @@ module SoftLayer
168
211
  packages_with_key_name('BARE_METAL_CPU', client)
169
212
  end
170
213
 
214
+ ##
215
+ # The "Additional Products" package is a grab-bag of products
216
+ # and services. It has a "well known" id of 0
217
+ def self.additional_products_package(client = nil)
218
+ return package_with_id(0, client)
219
+ end
220
+
171
221
  protected
172
222
 
173
223
  def self.default_object_mask(root)
@@ -16,6 +16,7 @@ module SoftLayer
16
16
  # ancestry. As a result there is no SoftLayer API analog
17
17
  # to this class.
18
18
  class Server < SoftLayer::ModelBase
19
+ include ::SoftLayer::DynamicAttribute
19
20
 
20
21
  ##
21
22
  # :attr_reader:
@@ -52,6 +53,17 @@ module SoftLayer
52
53
  # Notes about these server (for use by the customer)
53
54
  sl_attr :notes
54
55
 
56
+ sl_dynamic_attr :primary_network_component do |primary_component|
57
+ primary_component.should_update? do
58
+ return @primary_network_component == nil
59
+ end
60
+
61
+ primary_component.to_update do
62
+ component_data = self.service.getPrimaryNetworkComponent();
63
+ SoftLayer::NetworkComponent.new(self.softlayer_client, component_data)
64
+ end
65
+ end
66
+
55
67
  ##
56
68
  # Construct a server from the given client using the network data found in +network_hash+
57
69
  #
@@ -82,7 +94,7 @@ module SoftLayer
82
94
  when :power_cycle
83
95
  self.service.rebootHard
84
96
  else
85
- raise RuntimeError, "Unrecognized reboot technique in SoftLayer::Server#reboot!}"
97
+ raise ArgumentError, "Unrecognized reboot technique in SoftLayer::Server#reboot!}"
86
98
  end
87
99
  end
88
100
 
@@ -105,7 +117,7 @@ module SoftLayer
105
117
  # Change the notes of the server
106
118
  # raises ArgumentError if you pass nil as the notes
107
119
  def notes=(new_notes)
108
- raise ArgumentError.new("The new notes cannot be nil") unless new_notes
120
+ raise ArgumentError, "The new notes cannot be nil" unless new_notes
109
121
 
110
122
  edit_template = {
111
123
  "notes" => new_notes
@@ -119,7 +131,7 @@ module SoftLayer
119
131
  # Change the user metadata for the server.
120
132
  #
121
133
  def user_metadata=(new_metadata)
122
- raise ArgumentError.new("Cannot set user metadata to nil") unless new_metadata
134
+ raise ArgumentError, "Cannot set user metadata to nil" unless new_metadata
123
135
  self.service.setUserMetadata([new_metadata])
124
136
  self.refresh_details()
125
137
  end
@@ -129,8 +141,8 @@ module SoftLayer
129
141
  # Raises an ArgumentError if the new hostname is nil or empty
130
142
  #
131
143
  def set_hostname!(new_hostname)
132
- raise ArgumentError.new("The new hostname cannot be nil") unless new_hostname
133
- raise ArgumentError.new("The new hostname cannot be empty") if new_hostname.empty?
144
+ raise ArgumentError, "The new hostname cannot be nil" unless new_hostname
145
+ raise ArgumentError, "The new hostname cannot be empty" if new_hostname.empty?
134
146
 
135
147
  edit_template = {
136
148
  "hostname" => new_hostname
@@ -147,8 +159,8 @@ module SoftLayer
147
159
  # no further validation is done on the domain name
148
160
  #
149
161
  def set_domain!(new_domain)
150
- raise ArgumentError.new("The new hostname cannot be nil") unless new_domain
151
- raise ArgumentError.new("The new hostname cannot be empty") if new_domain.empty?
162
+ raise ArgumentError, "The new hostname cannot be nil" unless new_domain
163
+ raise ArgumentError, "The new hostname cannot be empty" if new_domain.empty?
152
164
 
153
165
  edit_template = {
154
166
  "domain" => new_domain
@@ -158,6 +170,16 @@ module SoftLayer
158
170
  self.refresh_details()
159
171
  end
160
172
 
173
+ ##
174
+ # Returns the max port speed of the public network interfaces of the server taking into account
175
+ # bound interface pairs (redundant network cards).
176
+ def firewall_port_speed
177
+ network_components = self.service.object_mask("mask[id,maxSpeed]").getFrontendNetworkComponents()
178
+ max_speeds = network_components.collect { |component| component['maxSpeed'] }
179
+
180
+ max_speeds.empty? ? 0 : max_speeds.max
181
+ end
182
+
161
183
  ##
162
184
  # Change the current port speed of the server
163
185
  #
@@ -166,8 +188,7 @@ module SoftLayer
166
188
  # on the port.
167
189
  #
168
190
  # Set +public+ to +false+ in order to change the speed of the
169
- # primary private network interface.
170
- #
191
+ # private network interface.
171
192
  def change_port_speed(new_speed, public = true)
172
193
  if public
173
194
  self.service.setPublicNetworkInterfaceSpeed(new_speed)
@@ -0,0 +1,263 @@
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
+ # The ServerFirewall class represents a firewall in the
10
+ # SoftLayer environment that exists in a 1 to 1 relationship
11
+ # with a particular server (either Bare Metal or Virtual).
12
+ #
13
+ # This is also called a "Shared Firewall" in some documentation.
14
+ #
15
+ # Instances of this class rougly correspond to instances of the
16
+ # SoftLayer_Network_Component_Firewall service entity.
17
+ #
18
+ class ServerFirewall < SoftLayer::ModelBase
19
+ include ::SoftLayer::DynamicAttribute
20
+
21
+ ##
22
+ # :attr_reader:
23
+ # The state of the firewall, includes whether or not the rules are
24
+ # editable and whether or not the firewall rules are applied or bypassed
25
+ # Can at least be 'allow_edit', 'bypass' or 'no_edit'.
26
+ # This list may not be exhaustive
27
+ sl_attr :status
28
+
29
+ ##
30
+ # :attr_reader:
31
+ # The firewall rules assigned to this firewall. These rules will
32
+ # be read from the network API every time you ask for the value
33
+ # of this property. To change the rules on the server use the
34
+ # asymmetric method change_rules!
35
+ sl_dynamic_attr :rules do |firewall_rules|
36
+ firewall_rules.should_update? do
37
+ # firewall rules update every time you ask for them.
38
+ return true
39
+ end
40
+
41
+ firewall_rules.to_update do
42
+ rules_data = self.service.object_mask(self.class.default_rules_mask).getRules()
43
+
44
+ # At the time of this writing, the object mask sent to getRules is not
45
+ # applied properly. This has been reported as a bug to the proper
46
+ # development team. In the mean time, this extra step does filtering
47
+ # that should have been done by the object mask.
48
+ rules_keys = self.class.default_rules_mask_keys
49
+ new_rules = rules_data.inject([]) do |new_rules, current_rule|
50
+ new_rule = current_rule.delete_if { |key, value| !(rules_keys.include? key) }
51
+ new_rules << new_rule
52
+ end
53
+
54
+ new_rules.sort { |lhs, rhs| lhs['orderValue'] <=> rhs['orderValue'] }
55
+ end
56
+ end
57
+
58
+ ##
59
+ # :attr_reader:
60
+ # The server that this firewall is attached to. The result may be
61
+ # either a bare metal or virtual server.
62
+ #
63
+ sl_dynamic_attr :protected_server do |protected_server|
64
+ protected_server.should_update? do
65
+ @protected_server == nil
66
+ end
67
+
68
+ protected_server.to_update do
69
+ if has_sl_property?('networkComponent')
70
+ @protected_server = SoftLayer::BareMetalServer.server_with_id(self['networkComponent']['downlinkComponent']['hardwareId'], :client => softlayer_client)
71
+ end
72
+
73
+ if has_sl_property?('guestNetworkComponent')
74
+ @protected_server = SoftLayer::VirtualServer.server_with_id(self['guestNetworkComponent']['guest']['id'], :client => softlayer_client)
75
+ end
76
+
77
+ @protected_server
78
+ end
79
+ end
80
+
81
+ ##
82
+ # Calls super to initialize the object then initializes some
83
+ # properties
84
+ def initialize(client, network_hash)
85
+ super(client, network_hash)
86
+ @protected_server = nil
87
+ end
88
+
89
+ ##
90
+ # Cancel the firewall
91
+ #
92
+ # This method cancels the firewall and releases its
93
+ # resources. The cancellation is processed immediately!
94
+ # Call this method with careful deliberation!
95
+ #
96
+ # Notes is a string that describes the reason for the
97
+ # cancellation. If empty or nil, a default string will
98
+ # be added
99
+ #
100
+ def cancel!(notes = nil)
101
+ user = self.softlayer_client[:Account].object_mask("mask[id,account]").getCurrentUser
102
+ notes = "Cancelled by a call to #{__method__} in the softlayer_api gem" if notes == nil || notes == ""
103
+
104
+ cancellation_request = {
105
+ 'accountId' => user['account']['id'],
106
+ 'userId' => user['id'],
107
+ 'items' => [ {
108
+ 'billingItemId' => self['billingItem']['id'],
109
+ 'immediateCancellationFlag' => true
110
+ } ],
111
+ 'notes' => notes
112
+ }
113
+
114
+ self.softlayer_client[:Billing_Item_Cancellation_Request].createObject(cancellation_request)
115
+ end
116
+
117
+ ##
118
+ # Change the set of rules for the firewall.
119
+ # The rules_data parameter should be an array of hashes where
120
+ # each hash gives the conditions of the rule. The keys of the
121
+ # hashes should be entries from the array returned by
122
+ # SoftLayer::ServerFirewall.default_rules_mask_keys
123
+ #
124
+ # *NOTE!* When changing the rules on the firewall, you must
125
+ # pass in a complete set of rules each time. The rules you
126
+ # submit will replace the entire ruleset on the destination
127
+ # firewall.
128
+ #
129
+ # *NOTE!* The rules themselves have an "orderValue" property.
130
+ # It is this property, and *not* the order that the rules are
131
+ # found in the rules_data array, which will determine in which
132
+ # order the firewall applies it's rules to incomming traffic.
133
+ #
134
+ # *NOTE!* Changes to the rules are not applied immediately
135
+ # on the server side. Instead, they are enqueued by the
136
+ # firewall update service and updated periodically. A typical
137
+ # update will take about one minute to apply, but times may vary
138
+ # depending on the system load and other circumstances.
139
+ def change_rules!(rules_data)
140
+ change_object = {
141
+ "networkComponentFirewallId" => self.id,
142
+ "rules" => rules_data
143
+ }
144
+
145
+ self.softlayer_client[:Network_Firewall_Update_Request].createObject(change_object)
146
+ end
147
+
148
+ ##
149
+ # This method asks the firewall to ignore its rule set and pass all traffic
150
+ # through the firewall. Compare the behavior of this routine with
151
+ # change_routing_bypass!
152
+ #
153
+ # It is important to note that changing the bypass to :bypass_firewall_rules
154
+ # removes ALL the protection offered by the firewall. This routine should be
155
+ # used with careful deliberation.
156
+ #
157
+ # Note that this routine queues a rule change and rule changes may take
158
+ # time to process. The change will probably not take effect immediately.
159
+ #
160
+ # The two symbols accepted as arguments by this routine are:
161
+ # :apply_firewall_rules - The rules of the firewall are applied to traffic. This is the default operating mode of the firewall
162
+ # :bypass_firewall_rules - The rules of the firewall are ignored. In this configuration the firewall provides no protection.
163
+ #
164
+ def change_rules_bypass!(bypass_symbol)
165
+ change_object = {
166
+ "networkComponentFirewallId" => self.id,
167
+ "rules" => self.rules
168
+ }
169
+
170
+ case bypass_symbol
171
+ when :apply_firewall_rules
172
+ change_object['bypassFlag'] = false
173
+ self.softlayer_client[:Network_Firewall_Update_Request].createObject(change_object)
174
+ when :bypass_firewall_rules
175
+ change_object['bypassFlag'] = true
176
+ self.softlayer_client[:Network_Firewall_Update_Request].createObject(change_object)
177
+ else
178
+ raise ArgumentError, "An invalid parameter was sent to #{__method__}. It accepts :apply_firewall_rules and :bypass_firewall_rules"
179
+ end
180
+ end
181
+
182
+ ##
183
+ # Locate and return all the server firewalls in the environment.
184
+ #
185
+ # These are a bit tricky to track down. The strategy we take here is
186
+ # to look at the account and find all the VLANs that do NOT have their
187
+ # "dedicatedFirewallFlag" set.
188
+ #
189
+ # With the list of VLANs in hand we check each to see if it has an
190
+ # firewallNetworkComponents (corresponding to bare metal servers) or
191
+ # firewallGuestNetworkComponents (corresponding to virtual servers) that
192
+ # have a status of "allow_edit". Each such component is a firewall
193
+ # interface on the VLAN with rules that the customer can edit.
194
+ #
195
+ # The collection of all those VLANs becomes the set of firewalls
196
+ # for the account.
197
+ #
198
+ def self.find_firewalls(client = nil)
199
+ softlayer_client = client || Client.default_client
200
+ raise "#{__method__} requires a client but none was given and Client::default_client is not set" if !softlayer_client
201
+
202
+ # Note that the dedicatedFirewallFlag is actually an integer and not a boolean
203
+ # so we compare it against 0
204
+ shared_vlans_filter = SoftLayer::ObjectFilter.new() { |filter|
205
+ filter.accept("networkVlans.dedicatedFirewallFlag").when_it is(0)
206
+ }
207
+
208
+ bare_metal_firewalls_data = []
209
+ virtual_firewalls_data = []
210
+
211
+ shared_vlans = softlayer_client[:Account].object_mask(network_vlan_mask).object_filter(shared_vlans_filter).getNetworkVlans
212
+ shared_vlans.each do |vlan_data|
213
+ bare_metal_firewalls_data.concat vlan_data['firewallNetworkComponents'].select { |network_component| network_component['status'] != 'no_edit'}
214
+ virtual_firewalls_data.concat vlan_data['firewallGuestNetworkComponents'].select { |network_component| network_component['status'] != 'no_edit'}
215
+ end
216
+
217
+ bare_metal_firewalls = bare_metal_firewalls_data.collect { |bare_metal_firewall_data|
218
+ self.new(softlayer_client, bare_metal_firewall_data)
219
+ }
220
+
221
+ virtual_server_firewalls = virtual_firewalls_data.collect { |virtual_firewall_data|
222
+ self.new(softlayer_client, virtual_firewall_data)
223
+ }
224
+
225
+ return bare_metal_firewalls + virtual_server_firewalls
226
+ end
227
+
228
+ #--
229
+ # Methods for the SoftLayer model
230
+ #++
231
+
232
+ def service
233
+ self.softlayer_client[:Network_Component_Firewall].object_with_id(self.id)
234
+ end
235
+
236
+ def softlayer_properties(object_mask = nil)
237
+ service = self.service
238
+ service = service.object_mask(object_mask) if object_mask
239
+
240
+ if self.has_sl_property?('networkComponent')
241
+ service.object_mask("mask[id,status,billingItem.id,networkComponent.downlinkComponent.hardwareId]").getObject
242
+ else
243
+ service.object_mask("mask[id,status,billingItem.id,guestNetworkComponent.guest.id]").getObject
244
+ end
245
+ end
246
+
247
+ #--
248
+ #++
249
+ private
250
+
251
+ def self.network_vlan_mask
252
+ "mask[firewallNetworkComponents[id,status,billingItem.id,networkComponent.downlinkComponent.hardwareId],firewallGuestNetworkComponents[id,status,billingItem.id,guestNetworkComponent.guest.id]]"
253
+ end
254
+
255
+ def self.default_rules_mask
256
+ return { "mask" => default_rules_mask_keys }.to_sl_object_mask
257
+ end
258
+
259
+ def self.default_rules_mask_keys
260
+ ['orderValue','action','destinationIpAddress','destinationIpSubnetMask',"protocol","destinationPortRangeStart","destinationPortRangeEnd",'sourceIpAddress',"sourceIpSubnetMask","version"]
261
+ end
262
+ end # ServerFirewall class
263
+ end # SoftLayer module