ruby-jss 0.6.7 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ruby-jss might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGES.md +6 -0
- data/bin/jss-webhook-server +3 -0
- data/bin/netseg-update +387 -0
- data/lib/jss/api_object/computer.rb +7 -2
- data/lib/jss/api_object/network_segment.rb +241 -140
- data/lib/jss/db_connection.rb +1 -1
- data/lib/jss/ruby_extensions/ipaddr.rb +16 -16
- data/lib/jss/version.rb +1 -1
- metadata +6 -4
- data/bin/subnet-update +0 -401
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0b5245057f32987e52e0753f330b6b2fdd3b5a26
|
4
|
+
data.tar.gz: 8028f472e0694cfc2dd1fbf93914369482fdddd5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4b8aaa54395cf65ccd910b15694edef02d70899169ef3f433f61721b2729d5b7af31558990bb88e2b48ef829079cf2f0bcf81fbe49f463059977e4ff39aef84
|
7
|
+
data.tar.gz: 8577fd4833e3f93c6582612210ca63dd2ec9da3249f1e199f1471c12569b5e7bdd247e42d1acb818f779a06ef57b5f7c97906995a1717c9548b906a1f44fceea
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Change History
|
2
2
|
|
3
|
+
## v0.7.0 2017-02-01
|
4
|
+
|
5
|
+
- JSS::NetworkSegment - many bugfixes and cleanup. I didn't really have a proper grasp of IP CIDR masks before and how the (don't) related to the IP ranges used by Network Segments in the JSS. They CIDRs and full netmasks can still be used to set the ending addresses of NetworkSegment objects, but the #cidr method is gone, since it was meaningless for segments that didn't match subnet-ranges.
|
6
|
+
- subnect-update, the example command in the bin directory, has been renamed to negseg-update. It's also been cleaned up and uses the new functionality of JSS::NetworkSegment.
|
7
|
+
- JSS::DBConnection - fixed a bug where meaningless IO 'stream closed' errors would appear when closing the DB connection.
|
8
|
+
|
3
9
|
## v0.6.7 2017-01-03
|
4
10
|
|
5
11
|
- Added class JSS::WebHook, which requires Jamf Pro 9.97 or higher.
|
data/bin/netseg-update
ADDED
@@ -0,0 +1,387 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
### Copyright 2017 Pixar
|
4
|
+
|
5
|
+
###
|
6
|
+
### Licensed under the Apache License, Version 2.0 (the "Apache License")
|
7
|
+
### with the following modification; you may not use this file except in
|
8
|
+
### compliance with the Apache License and the following modification to it:
|
9
|
+
### Section 6. Trademarks. is deleted and replaced with:
|
10
|
+
###
|
11
|
+
### 6. Trademarks. This License does not grant permission to use the trade
|
12
|
+
### names, trademarks, service marks, or product names of the Licensor
|
13
|
+
### and its affiliates, except as required to comply with Section 4(c) of
|
14
|
+
### the License and to reproduce the content of the NOTICE file.
|
15
|
+
###
|
16
|
+
### You may obtain a copy of the Apache License at
|
17
|
+
###
|
18
|
+
### http://www.apache.org/licenses/LICENSE-2.0
|
19
|
+
###
|
20
|
+
### Unless required by applicable law or agreed to in writing, software
|
21
|
+
### distributed under the Apache License with the above modification is
|
22
|
+
### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
23
|
+
### KIND, either express or implied. See the Apache License for the specific
|
24
|
+
### language governing permissions and limitations under the Apache License.
|
25
|
+
|
26
|
+
# == Synopsis
|
27
|
+
# Add, remove, or change the Network Segments in the JSS based on data from an input file
|
28
|
+
# in CSV, tab, or other delimited format.
|
29
|
+
#
|
30
|
+
# == Usage
|
31
|
+
# subnet-update [-t | -d delimiter] [-h] file
|
32
|
+
#
|
33
|
+
#
|
34
|
+
# == Author
|
35
|
+
# Chris Lasell <chrisl@pixar.com>
|
36
|
+
#
|
37
|
+
# == Copyright
|
38
|
+
# Copyright (c) 2014 Pixar Animation Studios
|
39
|
+
##############################
|
40
|
+
|
41
|
+
# Libraries
|
42
|
+
##############################
|
43
|
+
require 'ruby-jss'
|
44
|
+
require 'getoptlong'
|
45
|
+
require 'english'
|
46
|
+
load '/Users/chrisl/git/gemdev/ruby-jss/lib/jss/api_object/network_segment.rb'
|
47
|
+
|
48
|
+
# The app object
|
49
|
+
##############################
|
50
|
+
class App
|
51
|
+
|
52
|
+
# Constants
|
53
|
+
##############################
|
54
|
+
|
55
|
+
PROG_NAME = File.basename($PROGRAM_NAME)
|
56
|
+
|
57
|
+
USAGE = "Usage: #{PROG_NAME} [options] [--help] /path/to/file".freeze
|
58
|
+
|
59
|
+
POTENTIAL_COLUMNS = %i(name starting ending cidr mask).freeze
|
60
|
+
|
61
|
+
DEFAULT_CACHE_FILE = Pathname.new('~/.last_subnet_update').expand_path
|
62
|
+
|
63
|
+
DEFAULT_DELIMITER = "\t".freeze
|
64
|
+
|
65
|
+
DEFAULT_COLUMNS = [:name, :starting, :ending].freeze
|
66
|
+
|
67
|
+
DEFAULT_MANUAL_PREFIX = 'Manual-'.freeze
|
68
|
+
|
69
|
+
# define the cli opts
|
70
|
+
CLI_OPTS = GetoptLong.new(
|
71
|
+
['--help', '-H', GetoptLong::NO_ARGUMENT],
|
72
|
+
['--delimiter', '--delim', '-d', GetoptLong::REQUIRED_ARGUMENT],
|
73
|
+
['--header', '-h', GetoptLong::NO_ARGUMENT],
|
74
|
+
['--columns', '-c', GetoptLong::OPTIONAL_ARGUMENT],
|
75
|
+
['--manual-prefix', '-m', GetoptLong::OPTIONAL_ARGUMENT],
|
76
|
+
['--cache', GetoptLong::REQUIRED_ARGUMENT],
|
77
|
+
['--debug', GetoptLong::NO_ARGUMENT],
|
78
|
+
['--server', '-S', GetoptLong::OPTIONAL_ARGUMENT],
|
79
|
+
['--port', '-P', GetoptLong::OPTIONAL_ARGUMENT],
|
80
|
+
['--user', '-U', GetoptLong::OPTIONAL_ARGUMENT],
|
81
|
+
['--no-verify-cert', '-V', GetoptLong::NO_ARGUMENT],
|
82
|
+
['--timeout', '-T', GetoptLong::OPTIONAL_ARGUMENT],
|
83
|
+
['--no-op', '-N', GetoptLong::NO_ARGUMENT]
|
84
|
+
)
|
85
|
+
|
86
|
+
attr_reader :debug
|
87
|
+
|
88
|
+
def initialize(_args)
|
89
|
+
@getpass = $stdin.tty? ? :prompt : :stdin
|
90
|
+
set_defaults
|
91
|
+
parse_cli
|
92
|
+
check_opts
|
93
|
+
end # init
|
94
|
+
|
95
|
+
def set_defaults
|
96
|
+
@debug = false
|
97
|
+
@delim = DEFAULT_DELIMITER
|
98
|
+
@header = false
|
99
|
+
@columns = DEFAULT_COLUMNS
|
100
|
+
@cache_file = DEFAULT_CACHE_FILE
|
101
|
+
@manual_prefix = DEFAULT_MANUAL_PREFIX
|
102
|
+
@user = JSS::CONFIG.api_username
|
103
|
+
@server = JSS::CONFIG.api_server_name
|
104
|
+
end
|
105
|
+
|
106
|
+
def parse_cli
|
107
|
+
# parse the cli opts
|
108
|
+
CLI_OPTS.each do |opt, arg|
|
109
|
+
case opt
|
110
|
+
when '--help' then show_help
|
111
|
+
when '--delimiter' then @delim = arg
|
112
|
+
when '--header' then @header = true
|
113
|
+
when '--columns' then @columns = arg.split(',').map(&:to_sym)
|
114
|
+
when '--manual-prefix' then @manual_prefix = arg
|
115
|
+
when '--cache' then @cache_file = Pathname.new arg
|
116
|
+
when '--debug' then @debug = true
|
117
|
+
when '--server' then @server = arg
|
118
|
+
when '--port' then @port = arg
|
119
|
+
when '--user'then @user = arg
|
120
|
+
when '--no-verify-cert' then @verify_cert = false
|
121
|
+
when '--timeout' then @timeout = arg
|
122
|
+
when '--no-op' then @noop = true
|
123
|
+
end # case
|
124
|
+
end # each opt arg
|
125
|
+
@columns = nil if @columns && @columns.empty?
|
126
|
+
@file = Pathname.new ARGV.shift.to_s
|
127
|
+
end # parse_cli
|
128
|
+
|
129
|
+
def check_opts
|
130
|
+
raise JSS::MissingDataError, 'No JSS Username provided or found in the JSS gem config.' unless @user
|
131
|
+
raise JSS::MissingDataError, 'No JSS Server provided or found in the JSS gem config.' unless @server
|
132
|
+
raise ArgumentError, "No input file specified.\n#{USAGE}" unless @file
|
133
|
+
raise "Input file doesn't exist or is not readable: #{@file}" unless @file.readable?
|
134
|
+
end
|
135
|
+
|
136
|
+
# Go!
|
137
|
+
def run
|
138
|
+
unless data_file_changed?
|
139
|
+
puts "File hasn't changed since last time, no changes to make!"
|
140
|
+
return
|
141
|
+
end
|
142
|
+
|
143
|
+
connect_to_jss
|
144
|
+
|
145
|
+
@parsed_data = parse_file
|
146
|
+
|
147
|
+
update_network_segments
|
148
|
+
cache_latest_data
|
149
|
+
end # run
|
150
|
+
|
151
|
+
def connect_to_jss
|
152
|
+
JSS::API.connect(
|
153
|
+
server: @server,
|
154
|
+
port: @port,
|
155
|
+
verify_cert: @verify_cert,
|
156
|
+
user: @user,
|
157
|
+
pw: @getpass,
|
158
|
+
stdin_line: 1,
|
159
|
+
timeout: @timeout
|
160
|
+
)
|
161
|
+
end
|
162
|
+
|
163
|
+
def show_help
|
164
|
+
puts <<-FULLHELP
|
165
|
+
Update the JSS Network Segments from a delimited file of subnet information.
|
166
|
+
CAUTION: This script can delete Network Segments from your JSS.
|
167
|
+
See the --no-op option
|
168
|
+
#{USAGE}
|
169
|
+
|
170
|
+
Options:
|
171
|
+
-d, --delimiter - The field delimiter in the file, defaults to tab.
|
172
|
+
-c, --columns [col1,col2,col3]
|
173
|
+
- The column order in file, must include 'name', 'starting',
|
174
|
+
and either 'ending', 'mask', or 'cidr'
|
175
|
+
-h, --header - The first line of the file is a header line,
|
176
|
+
defining the columns
|
177
|
+
-m, --manual-prefix - Network Segment names in the file and the JSS with this
|
178
|
+
prefix are ignored. Defaults to 'Manual-'
|
179
|
+
--cache /path/.. - Where read/save the input data for comparison between runs.
|
180
|
+
Defaults to ~/.last_subnet_update
|
181
|
+
-S, --server srvr - specify the JSS API server name
|
182
|
+
-P, --port portnum - specify the JSS API port
|
183
|
+
-U, --user username - specify the JSS API user
|
184
|
+
-V, --no-verify-cert - Allow self-signed, unverified SSL certificate
|
185
|
+
-T, --timeout secs - specify the JSS API timeout
|
186
|
+
-N, --no-op - Don't make any changes in the JSS, just report what would
|
187
|
+
have be changed.
|
188
|
+
-H, --help - show this help
|
189
|
+
--debug - show the ruby backtrace when errors occur
|
190
|
+
|
191
|
+
This program parses the input file line by line (possibly accounting for a header line).
|
192
|
+
Each line defines the name and IP-range of a network segment.
|
193
|
+
|
194
|
+
- If a segment in the file doesn't exist in the JSS, it is created in the JSS.
|
195
|
+
- If a segment's range is different in the file, it is updated in the JSS.
|
196
|
+
- If a segment in the JSS doesn't exist in the file, it is deleted from the JSS.
|
197
|
+
|
198
|
+
Any network segments with names starting with the given --manual-prefix are ignored.
|
199
|
+
The default manual-prefix is 'Manual-' so, e.g. segments named 'Manual-isolated'
|
200
|
+
and 'Manual-special-servers' in the JSS won't be touched.
|
201
|
+
|
202
|
+
Input File:
|
203
|
+
- The file must contain three columns, separated by the --delimiter,
|
204
|
+
with these names, in any order:
|
205
|
+
- 'name' (the network segment name)
|
206
|
+
- 'starting' (the starting IP address of the network segment)
|
207
|
+
- ONE of:
|
208
|
+
- 'ending' (the ending IP address of the network segment)
|
209
|
+
- 'cidr' (the network range of the segment as a CIDR bitmask, e.g. '24')
|
210
|
+
- 'mask' (the network range of the segment as an IP mask, e.g. '255.255.255.0')
|
211
|
+
Notes:
|
212
|
+
- The --columns option is a comma-separted list of the three
|
213
|
+
column names above indicating the column-order in the file.
|
214
|
+
|
215
|
+
- If --columns are not provided, and --header is specified, the first line
|
216
|
+
is assumed to contain the column names, separated by the delimiter
|
217
|
+
|
218
|
+
- If --header is provided with --columns, the first line of the file is ignored.
|
219
|
+
|
220
|
+
- The raw data from the file is cached and compared to the input file at
|
221
|
+
the next run. If the data is identical, no changes are made.
|
222
|
+
|
223
|
+
- If no API connection settings are provided, they will be read from
|
224
|
+
/etc/ruby-jss.conf and ~/.ruby-jss.conf. See the ruby-jss docs for details.
|
225
|
+
|
226
|
+
- The password for the connection will be read from STDIN or prompted if needed
|
227
|
+
|
228
|
+
FULLHELP
|
229
|
+
exit 0
|
230
|
+
end
|
231
|
+
|
232
|
+
# parse the incoming data file into an Hash of Hashes,
|
233
|
+
# Top level keys are the NetSeg names,
|
234
|
+
# Subhashes have keys :starting, and :ending
|
235
|
+
# Exclude any with names starting with @manual_prefix
|
236
|
+
#
|
237
|
+
# @return [Hash<Hash>] The lines of the file, as hashes
|
238
|
+
#
|
239
|
+
def parse_file
|
240
|
+
puts 'Parsing the data file'
|
241
|
+
# split the data into an array by newline/return chars.
|
242
|
+
# this means files saved by excel or windows will work.
|
243
|
+
lines = @raw_data.split(/[\n\r]+/)
|
244
|
+
|
245
|
+
# remove the first line if its a header, and parse it into the columns
|
246
|
+
# if needed
|
247
|
+
if @header
|
248
|
+
header = lines.shift
|
249
|
+
@columns ||= header.split(/\s*#{@delim}\s*/).map(&:to_sym)
|
250
|
+
end
|
251
|
+
|
252
|
+
check_columns
|
253
|
+
|
254
|
+
parsed_data = {}
|
255
|
+
lines.each do |line|
|
256
|
+
parsed_line = parse_a_data_line line
|
257
|
+
next unless parsed_line
|
258
|
+
name = parsed_line.delete :name
|
259
|
+
parsed_data[name] = parsed_line
|
260
|
+
end
|
261
|
+
parsed_names = parsed_data.keys
|
262
|
+
jss_names = JSS::NetworkSegment.all_names.reject { |jss_name| jss_name.start_with? @manual_prefix }
|
263
|
+
@segments_to_add = parsed_names - jss_names
|
264
|
+
@segments_to_delete = jss_names - parsed_names
|
265
|
+
@segments_to_check_for_changes = parsed_names - @segments_to_add - @segments_to_delete
|
266
|
+
parsed_data
|
267
|
+
end # parse_file
|
268
|
+
|
269
|
+
def check_columns
|
270
|
+
raise "Columns must include 'name' and 'starting'" unless \
|
271
|
+
@columns.include?(:name) && \
|
272
|
+
@columns.include?(:starting)
|
273
|
+
raise "Columns must include either 'ending', 'cidr', or 'mask'" unless \
|
274
|
+
@columns.include?(:ending) || \
|
275
|
+
@columns.include?(:cidr) || \
|
276
|
+
@columns.include?(:mask)
|
277
|
+
@use_cidr = (@columns.include?(:cidr) || @columns.include?(:mask))
|
278
|
+
end
|
279
|
+
|
280
|
+
def parse_a_data_line(line)
|
281
|
+
parts = line.split(@delim).map(&:strip)
|
282
|
+
name = parts[@columns.index(:name)]
|
283
|
+
starting = parts[@columns.index(:starting)]
|
284
|
+
ending = parts[@columns.index(:ending)]
|
285
|
+
unless name && starting && ending
|
286
|
+
puts "Skipping invalid line: #{line}"
|
287
|
+
return nil
|
288
|
+
end
|
289
|
+
if name.start_with? @manual_prefix
|
290
|
+
puts "Ignoring line with manual_prefix: #{line}"
|
291
|
+
return nil
|
292
|
+
end
|
293
|
+
{ name: name, starting: starting, ending: ending }
|
294
|
+
end
|
295
|
+
|
296
|
+
def data_file_changed?
|
297
|
+
# read in the file
|
298
|
+
@raw_data = @file.read
|
299
|
+
return true unless @cache_file.exist?
|
300
|
+
@raw_data != @cache_file.read
|
301
|
+
end
|
302
|
+
|
303
|
+
def cache_latest_data
|
304
|
+
return if @noop
|
305
|
+
@cache_file.jss_save @raw_data
|
306
|
+
end
|
307
|
+
|
308
|
+
def update_network_segments
|
309
|
+
puts 'Applying changes'
|
310
|
+
add_segments
|
311
|
+
delete_segments
|
312
|
+
update_segments
|
313
|
+
puts 'Done!'
|
314
|
+
end # update_network_segments
|
315
|
+
|
316
|
+
def add_segments
|
317
|
+
@segments_to_add.each do |seg|
|
318
|
+
seg_data = @parsed_data[seg]
|
319
|
+
if @noop
|
320
|
+
connector = @use_cidr ? '/' : '->'
|
321
|
+
puts "Without --no-op this would: Add segment named '#{seg}', #{seg_data[:starting]}#{connector}#{seg_data[:ending]}"
|
322
|
+
next
|
323
|
+
end # if noop
|
324
|
+
|
325
|
+
ender = @use_cidr ? :cidr : :ending_address
|
326
|
+
new_seg = JSS::NetworkSegment.new(
|
327
|
+
:id => :new,
|
328
|
+
:name => seg,
|
329
|
+
:starting_address => seg_data[:starting],
|
330
|
+
ender => seg_data[:ending]
|
331
|
+
)
|
332
|
+
new_seg.create
|
333
|
+
puts "Added Network Segment '#{new_seg.name}' to the JSS"
|
334
|
+
end # @segments_to_add.each do |seg|
|
335
|
+
end # add_segments
|
336
|
+
|
337
|
+
def delete_segments
|
338
|
+
@segments_to_delete.each do |seg|
|
339
|
+
if @noop
|
340
|
+
puts "Without --no-op this would: Delete segment named '#{seg}',"
|
341
|
+
next
|
342
|
+
end # if noop
|
343
|
+
JSS::NetworkSegment.new(name: seg).delete
|
344
|
+
puts "Deleted Network Segment '#{seg}' from the JSS"
|
345
|
+
end # @segments_to_delete.each do |seg|
|
346
|
+
end # delete_segments
|
347
|
+
|
348
|
+
def update_segments
|
349
|
+
@segments_to_check_for_changes.each do |seg|
|
350
|
+
seg_data = @parsed_data[seg]
|
351
|
+
data_start = IPAddr.new(seg_data[:starting])
|
352
|
+
data_end = if @use_cidr
|
353
|
+
IPAddr.new("#{seg_data[:starting]}/#{seg_data[:ending]}").to_range.end.mask 32
|
354
|
+
else
|
355
|
+
IPAddr.new(seg_data[:ending])
|
356
|
+
end
|
357
|
+
|
358
|
+
this_seg = JSS::NetworkSegment.new name: seg
|
359
|
+
data_range = data_start..data_end
|
360
|
+
next if this_seg.range == data_range
|
361
|
+
|
362
|
+
if @noop
|
363
|
+
connector = @use_cidr ? '/' : '->'
|
364
|
+
puts "Without --no-op this would: Update segment named '#{seg}', #{seg_data[:starting]}#{connector}#{seg_data[:ending]}"
|
365
|
+
next
|
366
|
+
end # if noop
|
367
|
+
|
368
|
+
this_seg.set_ip_range starting_address: data_start, ending_address: data_end
|
369
|
+
this_seg.save
|
370
|
+
puts "Updated Network Segment '#{seg}' to range #{data_start} - #{data_end}"
|
371
|
+
end # @segments_to_check_for_changes.each do |seg|
|
372
|
+
end # update segments
|
373
|
+
|
374
|
+
end # app
|
375
|
+
|
376
|
+
##############################
|
377
|
+
# create the app and go
|
378
|
+
begin
|
379
|
+
debug = ARGV.include? '--debug'
|
380
|
+
app = App.new(ARGV)
|
381
|
+
app.run
|
382
|
+
rescue
|
383
|
+
# handle exceptions not handled elsewhere
|
384
|
+
puts "An error occurred: #{$ERROR_INFO}"
|
385
|
+
puts 'Backtrace:' if debug
|
386
|
+
puts $ERROR_POSITION if debug
|
387
|
+
end
|
@@ -60,8 +60,13 @@ module JSS
|
|
60
60
|
### * ip_address
|
61
61
|
### * udid
|
62
62
|
### * mac_addresses
|
63
|
-
### * location data
|
64
|
-
### * purchasing data
|
63
|
+
### * location data via the Locatable module
|
64
|
+
### * purchasing data via the Purchasable module
|
65
|
+
### * Extension Attribute values via the Extendable module
|
66
|
+
### Note: as with other 'recon' generated values, Ext. Attrs.
|
67
|
+
### populated by scripts cannot be modified via the API.
|
68
|
+
### (the change would be overwritten the next time the machine
|
69
|
+
### did a recon)
|
65
70
|
###
|
66
71
|
### After making any changes, you must call #update to send those
|
67
72
|
### changes to the server.
|
@@ -1,63 +1,56 @@
|
|
1
1
|
### Copyright 2017 Pixar
|
2
2
|
|
3
|
-
###
|
3
|
+
###
|
4
4
|
### Licensed under the Apache License, Version 2.0 (the "Apache License")
|
5
5
|
### with the following modification; you may not use this file except in
|
6
6
|
### compliance with the Apache License and the following modification to it:
|
7
7
|
### Section 6. Trademarks. is deleted and replaced with:
|
8
|
-
###
|
8
|
+
###
|
9
9
|
### 6. Trademarks. This License does not grant permission to use the trade
|
10
10
|
### names, trademarks, service marks, or product names of the Licensor
|
11
11
|
### and its affiliates, except as required to comply with Section 4(c) of
|
12
12
|
### the License and to reproduce the content of the NOTICE file.
|
13
|
-
###
|
13
|
+
###
|
14
14
|
### You may obtain a copy of the Apache License at
|
15
|
-
###
|
15
|
+
###
|
16
16
|
### http://www.apache.org/licenses/LICENSE-2.0
|
17
|
-
###
|
17
|
+
###
|
18
18
|
### Unless required by applicable law or agreed to in writing, software
|
19
19
|
### distributed under the Apache License with the above modification is
|
20
20
|
### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
21
21
|
### KIND, either express or implied. See the Apache License for the specific
|
22
22
|
### language governing permissions and limitations under the Apache License.
|
23
|
-
###
|
23
|
+
###
|
24
24
|
###
|
25
25
|
|
26
26
|
###
|
27
27
|
module JSS
|
28
28
|
|
29
|
-
#####################################
|
30
29
|
### Module Variables
|
31
30
|
#####################################
|
32
31
|
|
33
|
-
#####################################
|
34
32
|
### Module Methods
|
35
33
|
#####################################
|
36
34
|
|
37
|
-
#####################################
|
38
35
|
### Classes
|
39
36
|
#####################################
|
40
37
|
|
41
|
-
###
|
42
38
|
### A Network Segment in the JSS
|
43
39
|
###
|
44
|
-
### @see JSS::APIObject
|
45
40
|
###
|
46
|
-
class NetworkSegment
|
41
|
+
class NetworkSegment < JSS::APIObject
|
47
42
|
|
48
|
-
#####################################
|
49
43
|
### Mix Ins
|
50
44
|
#####################################
|
51
45
|
include JSS::Creatable
|
52
46
|
include JSS::Updatable
|
53
47
|
include Comparable
|
54
48
|
|
55
|
-
#####################################
|
56
49
|
### Class Constants
|
57
50
|
#####################################
|
58
51
|
|
59
52
|
### the REST resource base
|
60
|
-
RSRC_BASE =
|
53
|
+
RSRC_BASE = 'networksegments'.freeze
|
61
54
|
|
62
55
|
### the hash key used for the JSON list output of all objects in the JSS
|
63
56
|
RSRC_LIST_KEY = :network_segments
|
@@ -67,41 +60,124 @@ module JSS
|
|
67
60
|
RSRC_OBJECT_KEY = :network_segment
|
68
61
|
|
69
62
|
### these keys, as well as :id and :name, are present in valid API JSON data for this class
|
70
|
-
VALID_DATA_KEYS = [:distribution_point, :starting_address, :override_departments
|
71
|
-
|
72
|
-
#####################################
|
73
|
-
### Class Variables
|
74
|
-
#####################################
|
75
|
-
|
76
|
-
@@network_ranges = nil
|
63
|
+
VALID_DATA_KEYS = [:distribution_point, :starting_address, :override_departments].freeze
|
77
64
|
|
78
|
-
#####################################
|
79
65
|
### Class Methods
|
80
66
|
#####################################
|
81
67
|
|
68
|
+
### All NetworkSegments in the jss as IPAddr object Ranges representing the
|
69
|
+
### Segment, e.g. with starting = 10.24.9.1 and ending = 10.24.15.254
|
70
|
+
### the range looks like:
|
71
|
+
### <IPAddr: IPv4:10.24.9.1/255.255.255.255>..#<IPAddr: IPv4:10.24.15.254/255.255.255.255>
|
82
72
|
###
|
83
|
-
###
|
84
|
-
### subnet as a masked IPv4 address.
|
85
|
-
###
|
86
|
-
### Using the #include? and #to_range methods on those
|
87
|
-
### objects is very useful.
|
73
|
+
### Using the #include? method on those Ranges is very useful.
|
88
74
|
###
|
89
|
-
### @return [Hash{Integer =>
|
75
|
+
### @return [Hash{Integer => Range}] the network segments as IPv4 address Ranges
|
90
76
|
###
|
91
77
|
def self.network_ranges(refresh = false)
|
92
|
-
|
93
|
-
return
|
94
|
-
|
95
|
-
|
96
|
-
|
78
|
+
@network_ranges = nil if refresh
|
79
|
+
return @network_ranges if @network_ranges
|
80
|
+
@network_ranges = {}
|
81
|
+
all(refresh).each { |ns| @network_ranges[ns[:id]] = IPAddr.new(ns[:starting_address])..IPAddr.new(ns[:ending_address]) }
|
82
|
+
@network_ranges
|
97
83
|
end # def network_segments
|
98
84
|
|
99
|
-
###
|
100
85
|
### An alias for {NetworkSegment.network_ranges}
|
101
86
|
###
|
102
|
-
|
87
|
+
### DEPRECATED: This will be going away in a future release.
|
88
|
+
###
|
89
|
+
### @see {NetworkSegment::network_ranges}
|
90
|
+
###
|
91
|
+
def self.subnets(refresh = false)
|
92
|
+
network_ranges refresh
|
93
|
+
end
|
103
94
|
|
95
|
+
### Given a starting address & ending address, mask, or cidr,
|
96
|
+
### return a Range object of IPAddr objects.
|
97
|
+
###
|
98
|
+
### starting_address: must be provided, and may be a masked address,
|
99
|
+
### in which case nothing else is needed.
|
100
|
+
###
|
101
|
+
### If starting_address: is an unmasked address, then one of ending_address:
|
102
|
+
### cidr: or mask: must be provided.
|
103
|
+
###
|
104
|
+
### If given, ending_address: overrides mask:, cidr:, and a masked starting_address:
|
105
|
+
###
|
106
|
+
### These give the same result:
|
107
|
+
###
|
108
|
+
### ip_range starting_address: '192.168.1.0', ending_address: '192.168.1.255'
|
109
|
+
### ip_range starting_address: '192.168.1.0', mask: '255.255.255.0'
|
110
|
+
### ip_range starting_address: '192.168.1.0', cidr: 24
|
111
|
+
### ip_range starting_address: '192.168.1.0/24'
|
112
|
+
### ip_range starting_address: '192.168.1.0/255.255.255.0'
|
113
|
+
###
|
114
|
+
### All the above will produce:
|
115
|
+
### #<IPAddr: IPv4:192.168.1.0/255.255.255.255>..#<IPAddr: IPv4:192.168.1.255/255.255.255.255>
|
104
116
|
###
|
117
|
+
### An exception is raised if the starting address is above the ending address.
|
118
|
+
###
|
119
|
+
### @param starting_address[String] The starting address, possibly masked
|
120
|
+
###
|
121
|
+
### @param ending_address[String] The ending address. If given, it overrides mask:,
|
122
|
+
### cidr: and a masked starting_address:
|
123
|
+
###
|
124
|
+
### @param mask[String] The subnet mask to apply to the starting address to get
|
125
|
+
### the ending address
|
126
|
+
###
|
127
|
+
### @param cidr[String, Integer] he cidr value to apply to the starting address to get
|
128
|
+
### the ending address
|
129
|
+
###
|
130
|
+
### @return [Range<IPAddr>] the valid Range
|
131
|
+
###
|
132
|
+
def self.ip_range(starting_address: nil, ending_address: nil, mask: nil, cidr: nil)
|
133
|
+
raise JSS::MissingDataError, 'starting_address: must be provided' unless starting_address
|
134
|
+
|
135
|
+
starting_address = masked_starting_address(starting_address: starting_address, mask: mask, cidr: cidr)
|
136
|
+
|
137
|
+
if ending_address
|
138
|
+
startip = IPAddr.new starting_address.split('/').first
|
139
|
+
endip = IPAddr.new ending_address.to_s
|
140
|
+
validate_ip_range(startip, endip)
|
141
|
+
else
|
142
|
+
raise ArgumentError, 'Must provide ending_address:, mask:, cidr: or a masked starting_address:' unless starting_address.include? '/'
|
143
|
+
subnet = IPAddr.new starting_address
|
144
|
+
startip = subnet.to_range.first.mask 32
|
145
|
+
endip = subnet.to_range.last.mask 32
|
146
|
+
end
|
147
|
+
|
148
|
+
startip..endip
|
149
|
+
end
|
150
|
+
|
151
|
+
### If we are given a mask or cidr, append them to the starting_address
|
152
|
+
###
|
153
|
+
### @param starting[String] The starting address, possibly masked
|
154
|
+
###
|
155
|
+
### @param mask[String] The subnet mask to apply to the starting address to get
|
156
|
+
### the ending address
|
157
|
+
###
|
158
|
+
### @param cidr[String, Integer] he cidr value to apply to the starting address to get
|
159
|
+
### the ending address
|
160
|
+
###
|
161
|
+
### @return [String] the starting with the mask or cidr appended
|
162
|
+
###
|
163
|
+
def self.masked_starting_address(starting_address: nil, mask: nil, cidr: nil)
|
164
|
+
starting_address = "#{starting}/#{mask || cidr}" if mask || cidr
|
165
|
+
starting_address.to_s
|
166
|
+
end
|
167
|
+
|
168
|
+
### Raise an exception if a given starting ip is higher than a given ending ip
|
169
|
+
###
|
170
|
+
### @param startip[String] The starting ip
|
171
|
+
###
|
172
|
+
### @param endip[String] The ending ip
|
173
|
+
###
|
174
|
+
### @return [void]
|
175
|
+
###
|
176
|
+
def self.validate_ip_range(startip, endip)
|
177
|
+
return nil if IPAddr.new(startip.to_s) <= IPAddr.new(endip.to_s)
|
178
|
+
raise JSS::InvalidDataError, "Starting IP #{startip} is higher than ending ip #{endip} "
|
179
|
+
end
|
180
|
+
|
105
181
|
### Find the ids of the network segments that contain a given IP address.
|
106
182
|
###
|
107
183
|
### Even tho IPAddr.include? will take a String or an IPAddr
|
@@ -112,38 +188,38 @@ module JSS
|
|
112
188
|
###
|
113
189
|
### @return [Array<Integer>] the ids of the NetworkSegments containing the given ip
|
114
190
|
###
|
115
|
-
def self.
|
191
|
+
def self.network_segments_for_ip(ip)
|
116
192
|
ok_ip = IPAddr.new(ip)
|
117
193
|
matches = []
|
118
|
-
|
194
|
+
network_ranges.each { |id, subnet| matches << id if subnet.include?(ok_ip) }
|
119
195
|
matches
|
120
196
|
end
|
121
197
|
|
122
|
-
|
198
|
+
def self.network_segment_for_ip(ip)
|
199
|
+
network_segments_for_ip(ip)
|
200
|
+
end
|
201
|
+
|
123
202
|
### Find the current network segment ids for the machine running this code
|
124
203
|
###
|
125
204
|
### @return [Array<Integer>] the NetworkSegment ids for this machine right now.
|
126
205
|
###
|
127
|
-
def self.
|
206
|
+
def self.my_network_segments
|
128
207
|
network_segment_for_ip JSS::Client.my_ip_address
|
129
208
|
end
|
130
209
|
|
210
|
+
def self.my_network_segment
|
211
|
+
my_network_segments
|
212
|
+
end
|
131
213
|
|
132
|
-
|
133
|
-
#####################################
|
134
214
|
### Attributes
|
135
215
|
#####################################
|
136
216
|
|
137
|
-
|
138
217
|
### @return [IPAddr] starting IP adresss
|
139
218
|
attr_reader :starting_address
|
140
219
|
|
141
220
|
### @return [IPAddr] ending IP adresss
|
142
221
|
attr_reader :ending_address
|
143
222
|
|
144
|
-
### @return [Integer] the CIDR
|
145
|
-
attr_reader :cidr
|
146
|
-
|
147
223
|
### @return [String] building for this segment. Must be one of the buildings in the JSS
|
148
224
|
attr_reader :building
|
149
225
|
|
@@ -168,108 +244,127 @@ module JSS
|
|
168
244
|
### @return [Boolean] should machines checking in from this segment update their building
|
169
245
|
attr_reader :override_buildings
|
170
246
|
|
171
|
-
###
|
172
|
-
attr_reader :uid
|
173
|
-
|
174
|
-
### @return [IPAddr] the IPAddr object representing this network segment, created from the uid
|
175
|
-
attr_reader :subnet
|
176
|
-
|
247
|
+
### Instantiate a NetworkSegment
|
177
248
|
###
|
178
|
-
### @
|
249
|
+
### @see_also JSS::NetworkSegment.ip_range for how starting and ending
|
250
|
+
### addresses can be provided when using id: :new
|
179
251
|
###
|
180
|
-
def initialize(args = {}
|
181
|
-
|
252
|
+
def initialize(args = {})
|
182
253
|
super args
|
183
254
|
|
184
255
|
if args[:id] == :new
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
256
|
+
range = self.class.ip_range(
|
257
|
+
starting_address: args[:starting_address],
|
258
|
+
ending_address: args[:ending_address],
|
259
|
+
mask: args[:mask],
|
260
|
+
cidr: args[:cidr]
|
261
|
+
)
|
262
|
+
@init_data[:starting_address] = range.begin.to_s
|
263
|
+
@init_data[:ending_address] = range.end.to_s
|
190
264
|
end
|
191
265
|
|
266
|
+
@starting_address = IPAddr.new @init_data[:starting_address]
|
267
|
+
@ending_address = IPAddr.new @init_data[:ending_address]
|
268
|
+
|
192
269
|
@building = @init_data[:building]
|
193
270
|
@department = @init_data[:department]
|
194
271
|
@distribution_point = @init_data[:distribution_point]
|
195
272
|
@netboot_server = @init_data[:netboot_server]
|
196
273
|
@override_buildings = @init_data[:override_buildings]
|
197
274
|
@override_departments = @init_data[:override_departments]
|
198
|
-
@starting_address = IPAddr.new @init_data[:starting_address]
|
199
275
|
@swu_server = @init_data[:swu_server]
|
200
276
|
@url = @init_data[:url]
|
277
|
+
end # init
|
201
278
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
end # if args[:cidr]
|
211
|
-
|
212
|
-
### we now have all our data, make our unique identifier, the startingaddr/cidr
|
213
|
-
@uid = "#{@starting_address}/#{@cidr}"
|
214
|
-
|
215
|
-
### the IPAddr object for this whole net segment
|
216
|
-
@subnet = IPAddr.new @uid
|
217
|
-
|
218
|
-
end #init
|
279
|
+
### a Range built from the start and end addresses.
|
280
|
+
### To be used for finding inclusion and overlaps.
|
281
|
+
###
|
282
|
+
### @return [Range<IPAddr>] the range of IPAddrs for this segment.
|
283
|
+
###
|
284
|
+
def range
|
285
|
+
@starting_address..@ending_address
|
286
|
+
end
|
219
287
|
|
288
|
+
### Does this network segment overlap with another?
|
220
289
|
###
|
221
|
-
###
|
290
|
+
### @param other_segment[JSS::NetworkSegment] the other segment to check
|
222
291
|
###
|
223
|
-
###
|
292
|
+
### @return [Boolean] Does the other segment overlap this one?
|
293
|
+
###
|
294
|
+
def overlap?(other_segment)
|
295
|
+
raise TypeError, 'Argument must be a JSS::NetworkSegment' unless \
|
296
|
+
other_segment.is_a? JSS::NetworkSegment
|
297
|
+
other_range = other_segment.range
|
298
|
+
range.include?(other_range.begin) || range.include?(other_range.end)
|
299
|
+
end
|
300
|
+
|
301
|
+
### Does this network segment include an address or another segment?
|
302
|
+
### Inclusion means the other is completely inside this one.
|
224
303
|
###
|
225
|
-
### @
|
304
|
+
### @param thing[JSS::NetworkSegment, String, IPAddr] the other thing to check
|
226
305
|
###
|
227
|
-
|
228
|
-
|
306
|
+
### @return [Boolean] Does this segment include the other?
|
307
|
+
###
|
308
|
+
def include?(thing)
|
309
|
+
if thing.is_a? JSS::NetworkSegment
|
310
|
+
@starting_address <= thing.range.begin && @ending_address >= thing.range.end
|
311
|
+
else
|
312
|
+
thing = IPAddr.new thing.to_s
|
313
|
+
range.include? thing
|
314
|
+
end
|
229
315
|
end
|
230
316
|
|
317
|
+
### Does this network segment equal another?
|
318
|
+
### equality means the ranges are equal
|
319
|
+
###
|
320
|
+
### @param other_segment[JSS::NetworkSegment] the other segment to check
|
231
321
|
###
|
322
|
+
### @return [Boolean] Does this segment include the other?
|
323
|
+
###
|
324
|
+
def ==(other)
|
325
|
+
raise TypeError, 'Argument must be a JSS::NetworkSegment' unless \
|
326
|
+
other.is_a? JSS::NetworkSegment
|
327
|
+
range == other.range
|
328
|
+
end
|
329
|
+
|
232
330
|
### Set the building
|
233
331
|
###
|
234
332
|
### @param newval[String, Integer] the new building by name or id, must be in the JSS
|
235
333
|
###
|
236
334
|
### @return [void]
|
237
335
|
###
|
238
|
-
def building=
|
239
|
-
new = JSS::Building.all.select{|b| b[:id] == newval
|
336
|
+
def building=(newval)
|
337
|
+
new = JSS::Building.all.select { |b| (b[:id] == newval) || (b[:name] == newval) }[0]
|
240
338
|
raise JSS::MissingDataError, "No building matching '#{newval}'" unless new
|
241
339
|
@building = new[:name]
|
242
340
|
@need_to_update = true
|
243
341
|
end
|
244
342
|
|
245
|
-
###
|
246
343
|
### set the override buildings option
|
247
344
|
###
|
248
345
|
### @param newval[Boolean] the new override buildings option
|
249
346
|
###
|
250
347
|
### @return [void]
|
251
348
|
###
|
252
|
-
def override_buildings=
|
253
|
-
raise JSS::InvalidDataError,
|
349
|
+
def override_buildings=(newval)
|
350
|
+
raise JSS::InvalidDataError, 'New value must be boolean true or false' unless JSS::TRUE_FALSE.include? newval
|
254
351
|
@override_buildings = newval
|
255
352
|
@need_to_update = true
|
256
353
|
end
|
257
354
|
|
258
|
-
###
|
259
355
|
### set the department
|
260
356
|
###
|
261
357
|
### @param newval[String, Integer] the new dept by name or id, must be in the JSS
|
262
358
|
###
|
263
359
|
### @return [void]
|
264
360
|
###
|
265
|
-
def department=
|
266
|
-
new = JSS::Department.all.select{|b| b[:id] == newval
|
361
|
+
def department=(newval)
|
362
|
+
new = JSS::Department.all.select { |b| (b[:id] == newval) || (b[:name] == newval) }[0]
|
267
363
|
raise JSS::MissingDataError, "No department matching '#{newval}' in the JSS" unless new
|
268
364
|
@department = new[:name]
|
269
365
|
@need_to_update = true
|
270
366
|
end
|
271
367
|
|
272
|
-
###
|
273
368
|
### set the override depts option
|
274
369
|
###
|
275
370
|
### @param newval[Boolean] the new setting
|
@@ -277,139 +372,145 @@ module JSS
|
|
277
372
|
### @return [void]
|
278
373
|
###
|
279
374
|
###
|
280
|
-
def override_departments=
|
281
|
-
raise JSS::InvalidDataError,
|
375
|
+
def override_departments=(newval)
|
376
|
+
raise JSS::InvalidDataError, 'New value must be boolean true or false' unless JSS::TRUE_FALSE.include? newval
|
282
377
|
@override_departments = newval
|
283
378
|
@need_to_update = true
|
284
379
|
end
|
285
380
|
|
286
|
-
###
|
287
381
|
### set the distribution_point
|
288
382
|
###
|
289
383
|
### @param newval[String, Integer] the new dist. point by name or id, must be in the JSS
|
290
384
|
###
|
291
385
|
### @return [void]
|
292
386
|
###
|
293
|
-
def distribution_point=
|
294
|
-
new = JSS::DistributionPoint.all.select{|b| b[:id] == newval
|
387
|
+
def distribution_point=(newval)
|
388
|
+
new = JSS::DistributionPoint.all.select { |b| (b[:id] == newval) || (b[:name] == newval) }[0]
|
295
389
|
raise JSS::MissingDataError, "No distribution_point matching '#{newval}' in the JSS" unless new
|
296
390
|
@distribution_point = new[:name]
|
297
391
|
@need_to_update = true
|
298
392
|
end
|
299
393
|
|
300
|
-
###
|
301
394
|
### set the netboot_server
|
302
395
|
###
|
303
396
|
### @param newval[String, Integer] the new netboot server by name or id, must be in the JSS
|
304
397
|
###
|
305
398
|
### @return [void]
|
306
399
|
###
|
307
|
-
def netboot_server=
|
308
|
-
new = JSS::NetbootServer.all.select{|b| b[:id] == newval
|
400
|
+
def netboot_server=(newval)
|
401
|
+
new = JSS::NetbootServer.all.select { |b| (b[:id] == newval) || (b[:name] == newval) }[0]
|
309
402
|
raise JSS::MissingDataError, "No netboot_server matching '#{newval}' in the JSS" unless new
|
310
403
|
@netboot_server = new[:name]
|
311
404
|
@need_to_update = true
|
312
405
|
end
|
313
406
|
|
314
|
-
###
|
315
407
|
### set the sw update server
|
316
408
|
###
|
317
409
|
### @param newval[String, Integer] the new server by name or id, must be in the JSS
|
318
410
|
###
|
319
411
|
### @return [void]
|
320
412
|
###
|
321
|
-
def swu_server=
|
322
|
-
new = JSS::SoftwareUpdateServer.all.select{|b| b[:id] == newval
|
413
|
+
def swu_server=(newval)
|
414
|
+
new = JSS::SoftwareUpdateServer.all.select { |b| (b[:id] == newval) || (b[:name] == newval) }[0]
|
323
415
|
raise JSS::MissingDataError, "No swu_server matching '#{newval}' in the JSS" unless new
|
324
416
|
@swu_server = new[:name]
|
325
417
|
@need_to_update = true
|
326
418
|
end
|
327
419
|
|
328
|
-
###
|
329
420
|
### set the starting address
|
330
421
|
###
|
331
422
|
### @param newval[String, IPAddr] the new starting address
|
332
423
|
###
|
333
424
|
### @return [void]
|
334
425
|
###
|
335
|
-
def starting_address=
|
336
|
-
|
337
|
-
|
338
|
-
@cidr = IPAddr.jss_cidr_from_ends(@starting_address ,@ending_address)
|
339
|
-
@uid = "#{@starting_address}/#{@cidr}"
|
340
|
-
@subnet = IPAddr.new @uid
|
426
|
+
def starting_address=(newval)
|
427
|
+
self.class.validate_ip_range(newval, @ending_address)
|
428
|
+
@starting_address = IPAddr.new newval.to_s
|
341
429
|
@need_to_update = true
|
342
430
|
end
|
343
431
|
|
344
|
-
###
|
345
432
|
### set the ending address
|
346
433
|
###
|
347
434
|
### @param newval[String, IPAddr] the new ending address
|
348
435
|
###
|
349
436
|
### @return [void]
|
350
437
|
###
|
351
|
-
def ending_address=
|
352
|
-
@
|
353
|
-
|
354
|
-
@cidr = IPAddr.jss_cidr_from_ends(@starting_address,@ending_address)
|
355
|
-
@uid = "#{@starting_address}/#{@cidr}"
|
356
|
-
@subnet = IPAddr.new @uid
|
438
|
+
def ending_address=(newval)
|
439
|
+
self.class.validate_ip_range(@starting_address, newval)
|
440
|
+
@ending_address = IPAddr.new newval.to_s
|
357
441
|
@need_to_update = true
|
358
442
|
end
|
359
443
|
|
444
|
+
### set the ending address by applying a new cidr (e.g. 24)
|
445
|
+
### or mask (e.g. 255.255.255.0)
|
360
446
|
###
|
361
|
-
###
|
362
|
-
###
|
363
|
-
### @param newval[String, IPAddr] the new cidr
|
447
|
+
### @param newval[String, Integer] the new cidr or mask
|
364
448
|
###
|
365
449
|
### @return [void]
|
366
450
|
###
|
367
|
-
def cidr=
|
368
|
-
|
369
|
-
|
370
|
-
@
|
371
|
-
@subnet = IPAddr.new @uid
|
451
|
+
def cidr=(newval)
|
452
|
+
new_end = IPAddr.new("#{@starting_address}/#{newval}").to_range.end.mask 32
|
453
|
+
self.class.validate_ip_range(@starting_address, new_end)
|
454
|
+
@ending_address = new_end
|
372
455
|
@need_to_update = true
|
373
456
|
end
|
374
457
|
|
458
|
+
### set a new starting and ending addr at the same time.
|
459
|
+
###
|
460
|
+
### @see_also NetworkSegment.ip_range for how to specify the starting
|
461
|
+
### and ending addresses.
|
462
|
+
###
|
463
|
+
### @param starting_address[String] The starting address, possibly masked
|
375
464
|
###
|
376
|
-
###
|
465
|
+
### @param ending_address[String] The ending address
|
377
466
|
###
|
378
|
-
### @param
|
467
|
+
### @param mask[String] The subnet mask to apply to the starting address to get
|
468
|
+
### the ending address
|
379
469
|
###
|
380
|
-
### @
|
470
|
+
### @param cidr[String, Integer] he cidr value to apply to the starting address to get
|
471
|
+
### the ending address
|
381
472
|
###
|
382
|
-
|
383
|
-
|
473
|
+
### @return [void]
|
474
|
+
###
|
475
|
+
def set_ip_range(starting_address: nil, ending_address: nil, mask: nil, cidr: nil)
|
476
|
+
range = self.class.ip_range(
|
477
|
+
starting_address: starting_address,
|
478
|
+
ending_address: ending_address,
|
479
|
+
mask: mask,
|
480
|
+
cidr: cidr
|
481
|
+
)
|
482
|
+
@starting_address = range.first
|
483
|
+
@ending_address = range.last
|
484
|
+
@need_to_update = true
|
384
485
|
end
|
385
486
|
|
386
|
-
|
387
487
|
### aliases
|
388
|
-
alias identifier uid
|
389
|
-
alias range subnet
|
390
|
-
|
391
488
|
######################
|
489
|
+
alias mask= cidr=
|
490
|
+
alias to_range range
|
491
|
+
|
392
492
|
### private methods
|
493
|
+
######################
|
393
494
|
private
|
394
495
|
|
395
|
-
###
|
396
496
|
### the xml formated data for adding or updating this in the JSS
|
397
497
|
###
|
398
498
|
def rest_xml
|
399
499
|
doc = REXML::Document.new APIConnection::XML_HEADER
|
400
|
-
ns = doc.add_element
|
500
|
+
ns = doc.add_element 'network_segment'
|
401
501
|
ns.add_element('building').text = @building
|
402
502
|
ns.add_element('department').text = @department
|
403
503
|
ns.add_element('distribution_point').text = @distribution_point
|
404
|
-
ns.add_element('ending_address').text = @ending_address
|
504
|
+
ns.add_element('ending_address').text = @ending_address.to_s
|
405
505
|
ns.add_element('name').text = @name
|
406
506
|
ns.add_element('netboot_server').text = @netboot_server
|
407
507
|
ns.add_element('override_buildings').text = @override_buildings
|
408
508
|
ns.add_element('override_departments').text = @override_departments
|
409
|
-
ns.add_element('starting_address').text = @starting_address
|
509
|
+
ns.add_element('starting_address').text = @starting_address.to_s
|
410
510
|
ns.add_element('swu_server').text = @swu_server
|
411
|
-
|
412
|
-
end #rest_xml
|
511
|
+
doc.to_s
|
512
|
+
end # rest_xml
|
413
513
|
|
414
514
|
end # class NetworkSegment
|
515
|
+
|
415
516
|
end # module
|