softlayer_api 3.0.b1 → 3.0.b2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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