nv-client 1.66.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README +5 -0
- data/Rakefile +2 -0
- data/bin/nv +709 -0
- data/lib/nv-client.rb +5 -0
- data/lib/nv-client/version.rb +5 -0
- data/lib/nventory.rb +2086 -0
- data/nv-client.gemspec +22 -0
- metadata +85 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README
ADDED
data/Rakefile
ADDED
data/bin/nv
ADDED
@@ -0,0 +1,709 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
##############################################################################
|
3
|
+
# A client to query a nVentory server
|
4
|
+
##############################################################################
|
5
|
+
|
6
|
+
require 'optparse'
|
7
|
+
require 'nventory'
|
8
|
+
|
9
|
+
# Ensure we have a sane path, particularly since we might be run from
|
10
|
+
# cron in registration mode.
|
11
|
+
ENV['PATH'] = '/bin:/usr/bin:/sbin:/usr/sbin'
|
12
|
+
|
13
|
+
#
|
14
|
+
# Process command line options
|
15
|
+
#
|
16
|
+
|
17
|
+
$objecttype = 'nodes'
|
18
|
+
$get = nil
|
19
|
+
$exactget = nil
|
20
|
+
$regexget = nil
|
21
|
+
$and = nil
|
22
|
+
$exclude = nil
|
23
|
+
$name = nil
|
24
|
+
$allfields = nil
|
25
|
+
$fields = nil
|
26
|
+
$set = nil
|
27
|
+
$yes = false
|
28
|
+
$getfieldnames = false
|
29
|
+
$getallvalues = nil
|
30
|
+
$nodegroup = nil
|
31
|
+
$nodegroupexpanded = nil
|
32
|
+
$createnodegroup = nil
|
33
|
+
$addnodegroupnodeassignments = nil
|
34
|
+
$addtonodegroup = nil
|
35
|
+
$removefromnodegroup = nil
|
36
|
+
$addnodegrouptonodegroup = nil
|
37
|
+
$addcomment = nil
|
38
|
+
$removenodegroupfromnodegroup = nil
|
39
|
+
$createtag = nil
|
40
|
+
$addtagtonodegroup = nil
|
41
|
+
$removetagfromnodegroup = nil
|
42
|
+
$register = false
|
43
|
+
$username = ENV['LOGNAME']
|
44
|
+
$delete = nil
|
45
|
+
$showtags = nil
|
46
|
+
$withaliases = nil
|
47
|
+
$debug = nil
|
48
|
+
$dryrun = nil
|
49
|
+
$server = nil
|
50
|
+
|
51
|
+
def singularize(string)
|
52
|
+
if string =~ /(.*s)es$/
|
53
|
+
singular = $1
|
54
|
+
elsif string =~ /(.*)s$/
|
55
|
+
singular = $1;
|
56
|
+
else
|
57
|
+
singular = string
|
58
|
+
end
|
59
|
+
return singular;
|
60
|
+
end
|
61
|
+
|
62
|
+
def opt_hash_parse(opt)
|
63
|
+
opthash = {}
|
64
|
+
current_field = nil
|
65
|
+
opt.split(',').each do |entry|
|
66
|
+
if (entry =~ /(.+)=(.+)/)
|
67
|
+
current_field = $1
|
68
|
+
opthash[current_field] = [$2]
|
69
|
+
else
|
70
|
+
if current_field
|
71
|
+
opthash[current_field] << entry
|
72
|
+
else
|
73
|
+
abort "Failed to parse '#{opt}' as a series of name=value[,value] pairs"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
opthash
|
78
|
+
end
|
79
|
+
|
80
|
+
opts = OptionParser.new
|
81
|
+
opts.banner = 'Usage: nv [options]'
|
82
|
+
opts.on('--objecttype object',
|
83
|
+
'The type of object to get/set. Defaults to nodes.') do |opt|
|
84
|
+
$objecttype = opt
|
85
|
+
end
|
86
|
+
opts.on('--get [field=value1,value2][,field2=value1[,value2]]') do |opt|
|
87
|
+
if opt.nil?
|
88
|
+
$get = {}
|
89
|
+
else
|
90
|
+
$get = opt_hash_parse(opt)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
opts.on('--showtags', 'Lists all tags the node(s) belongs to') do |opt|
|
94
|
+
$showtags = opt
|
95
|
+
end
|
96
|
+
opts.on('--delete', 'Delete the object(s) returned') do |opt|
|
97
|
+
$delete = opt
|
98
|
+
end
|
99
|
+
opts.on('--exactget [field=value1,value2]',
|
100
|
+
'Select objects for display or updating. get does a substring',
|
101
|
+
'match, exactget does an exact match. Multiple fields and values ',
|
102
|
+
'can be specified seperated by commas.') do |opt|
|
103
|
+
if opt.nil?
|
104
|
+
$exactget = {}
|
105
|
+
else
|
106
|
+
$exactget = opt_hash_parse(opt)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
opts.on('--regexget [field=value1,value2]',
|
110
|
+
'Select objects for display or updating. get does a substring',
|
111
|
+
'match, regexget does an regexp match. Multiple fields and values ',
|
112
|
+
'can be specified seperated by commas.') do |opt|
|
113
|
+
if opt.nil?
|
114
|
+
$regexget = {}
|
115
|
+
else
|
116
|
+
$regexget = opt_hash_parse(opt)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
opts.on('--exclude [field=value1,value2]',
|
120
|
+
'Select objects for display or updating. get does a substring',
|
121
|
+
'match, exclude does an regexp match. Multiple fields and values ',
|
122
|
+
'can be specified seperated by commas.') do |opt|
|
123
|
+
if opt.nil?
|
124
|
+
$exclude = {}
|
125
|
+
else
|
126
|
+
$exclude = opt_hash_parse(opt)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
opts.on('--and [field=value1,value2]',
|
130
|
+
'when doing get, search AND values on same field',
|
131
|
+
'can be specified seperated by commas.') do |opt|
|
132
|
+
if opt.nil?
|
133
|
+
$and = {}
|
134
|
+
else
|
135
|
+
$and = opt_hash_parse(opt)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
opts.on('--name value[,value2]', Array,
|
139
|
+
'Shortcut for --get name=value') do |opt|
|
140
|
+
$name = opt
|
141
|
+
end
|
142
|
+
opts.on('--addcomment "add your comment here"', Array) do |opt|
|
143
|
+
$addcomment = opt
|
144
|
+
end
|
145
|
+
opts.on('--allfields [excludefield1[,excludefield2]]', Array,
|
146
|
+
'Display all fields for selected objects.',
|
147
|
+
'One or more fields may be specified to be excluded from the',
|
148
|
+
'query, seperate multiple fields with commas.') do |opt|
|
149
|
+
if opt.nil?
|
150
|
+
$allfields = []
|
151
|
+
else
|
152
|
+
$allfields = opt
|
153
|
+
end
|
154
|
+
end
|
155
|
+
opts.on('--fields field1[,field2]', Array,
|
156
|
+
'Display the specified fields for selected objects.',
|
157
|
+
'One or more fields may be specified, either by specifying this',
|
158
|
+
'option multiple times or by seperating the field names with',
|
159
|
+
'commas.') do |opt|
|
160
|
+
if opt.nil?
|
161
|
+
$fields = []
|
162
|
+
else
|
163
|
+
$fields = opt
|
164
|
+
end
|
165
|
+
end
|
166
|
+
opts.on('--set field=value1[,value2][,field2=value1[,value2]]',
|
167
|
+
'Update fields in objects selected via get/exactget/regexget/exclude, Multiple ',
|
168
|
+
'fields and values can be specified seperated by commas.') do |opt|
|
169
|
+
$set = opt_hash_parse(opt)
|
170
|
+
end
|
171
|
+
opts.on('--yes',
|
172
|
+
'Don\'t prompt for set confirmation') do |opt|
|
173
|
+
$yes = true
|
174
|
+
end
|
175
|
+
opts.on('--getfieldnames',
|
176
|
+
'Shows get/set fields supported by server') do |opt|
|
177
|
+
$getfieldnames = true
|
178
|
+
end
|
179
|
+
opts.on('--getallvalues field1[,field2]', Array,
|
180
|
+
'Display all values stored in the database for the specified fields') do |opt|
|
181
|
+
$getallvalues = opt
|
182
|
+
end
|
183
|
+
opts.on('--nodegroup nodegroup', '--ng nodegroup',
|
184
|
+
'Display the members of the given node group, member groups are',
|
185
|
+
'displayed as groups and are not expanded') do |opt|
|
186
|
+
$nodegroup = opt
|
187
|
+
end
|
188
|
+
opts.on('--nodegroupexpanded nodegroup[,nodegroup2]', '--nge nodegroup', '--get_nodegroup_nodes nodegroup', '--get_ngn nodegroup', Array,
|
189
|
+
'Display the members of the given node groups, member groups are',
|
190
|
+
'expanded') do |opt|
|
191
|
+
$nodegroupexpanded = opt
|
192
|
+
end
|
193
|
+
opts.on('--createnodegroup nodegroup1[,nodegroup2]', Array,
|
194
|
+
'Create one or more node groups') do |opt|
|
195
|
+
$createnodegroup = opt
|
196
|
+
end
|
197
|
+
opts.on('--addnodegroupnodeassignments nodegroup1[,nodegroup2]', Array,
|
198
|
+
'Assign nodes selected via get/exactget/regexget/exclude to one or more node groups') do |opt|
|
199
|
+
$addnodegroupnodeassignments = opt
|
200
|
+
end
|
201
|
+
opts.on('--addtonodegroup nodegroup1[,nodegroup2]', Array,
|
202
|
+
'Add nodes selected via get/exactget/regexget/exclude to one or more node groups') do |opt|
|
203
|
+
$addtonodegroup = opt
|
204
|
+
end
|
205
|
+
opts.on('--removefromnodegroup nodegroup1[,nodegroup2]', Array,
|
206
|
+
'Remove nodes selected via get/exactget/regexget/exclude from one or more node groups') do |opt|
|
207
|
+
$removefromnodegroup = opt
|
208
|
+
end
|
209
|
+
opts.on('--addnodegrouptonodegroup child_group,parent_group', Array,
|
210
|
+
'Takes two node group names seperated by a comma, adds the first',
|
211
|
+
'node group to the second') do |opt|
|
212
|
+
$addnodegrouptonodegroup = [opt[0],opt[1]]
|
213
|
+
end
|
214
|
+
opts.on('--removenodegroupfromnodegroup child_group,parent_group', Array,
|
215
|
+
'Takes two node group names seperated by a comma, removes the first',
|
216
|
+
'node group from the second') do |opt|
|
217
|
+
$removenodegroupfromnodegroup = [opt[0],opt[1]]
|
218
|
+
end
|
219
|
+
opts.on('--createtag tagname1[,tagname2]', Array,
|
220
|
+
'Create one or more tags by name') do |opt|
|
221
|
+
$createtag= opt
|
222
|
+
end
|
223
|
+
opts.on('--addtagtonodegroup tag,node_group', Array,
|
224
|
+
'adds a tag to a node_group') do |opt|
|
225
|
+
$addtagtonodegroup = [opt[0],opt[1]]
|
226
|
+
end
|
227
|
+
opts.on('--removetagfromnodegroup tag,node_group', Array,
|
228
|
+
'removes a tag from a node_group') do |opt|
|
229
|
+
$removetagfromnodegroup = [opt[0],opt[1]]
|
230
|
+
end
|
231
|
+
opts.on('--register',
|
232
|
+
'Gather as much information as possible about the local machine',
|
233
|
+
'and register that information into the nVentory database.') do |opt|
|
234
|
+
$register = true
|
235
|
+
end
|
236
|
+
opts.on('--username value', String,
|
237
|
+
'Username to use when authenticating to the server. If not',
|
238
|
+
'specified defaults to the current user.') do |opt|
|
239
|
+
$username = opt
|
240
|
+
end
|
241
|
+
opts.on('--server value', String, 'Specify alternate server to query.') do |opt|
|
242
|
+
$server = opt
|
243
|
+
end
|
244
|
+
opts.on('--debug') do |opt|
|
245
|
+
$debug = opt
|
246
|
+
end
|
247
|
+
opts.on('--withaliases') do |opt|
|
248
|
+
$withaliases = opt
|
249
|
+
end
|
250
|
+
opts.on('--dry-run') do |opt|
|
251
|
+
$dryrun = opt
|
252
|
+
end
|
253
|
+
opts.separator ''
|
254
|
+
opts.separator('All options can be shortened to anything that\'s unique.')
|
255
|
+
opts.on_tail('--help') do
|
256
|
+
puts opts
|
257
|
+
exit
|
258
|
+
end
|
259
|
+
|
260
|
+
opts.parse(ARGV)
|
261
|
+
|
262
|
+
(puts opts; exit) unless $get || $exactget || $regexget || $name || $getfieldnames || $getallvalues || $register || $nodegroup || $nodegroupexpanded || $createnodegroup || $addnodegrouptonodegroup || $removenodegroupfromnodegroup || $addtagtonodegroup || $createtag || $removetagfromnodegroup
|
263
|
+
# These options are mutually exclusive
|
264
|
+
(puts opts; exit) if $allfields && $fields
|
265
|
+
(puts opts; exit) if $getfieldnames && ($get || $exactget || $regexget || $name)
|
266
|
+
(puts opts; exit) if $getallvalues && ($get || $exactget || $regexget || $name)
|
267
|
+
# FIXME: Should support searches on node group membership and other characteristics
|
268
|
+
(puts opts; exit) if ($nodegroup || $nodegroupexpanded) && ($get || $exactget || $regexget || $exclude || $name || $and)
|
269
|
+
(puts opts; exit) if $register && ($get || $exactget || $regexget || $exclude || $name || $getfieldnames || $getallvalues || $nodegroup || $nodegroupexpanded || $createnodegroup || $addnodegrouptonodegroup || $removenodegroupfromnodegroup || $and || $createtag || $addtagtonodegroup || $removetagfromnodegroup)
|
270
|
+
(puts opts; exit) if ($addtonodegroup || $addnodegroupnodeassignments || $removefromnodegroup || $addtagtonodegroup || $removetagfromnodegroup) && $objecttype != 'nodes'
|
271
|
+
(puts '--showtags can only be used if objecttype = nodes'; exit) if $showtags && ($objecttype !~ /^(nodes|node_groups)$/)
|
272
|
+
|
273
|
+
if $name
|
274
|
+
$get = {} if !$get
|
275
|
+
$get['name'] = $name
|
276
|
+
end
|
277
|
+
|
278
|
+
SEARCH_SHORTCUTS = {
|
279
|
+
'hw' => 'hardware_profile[name]',
|
280
|
+
'hwmanuf' => 'hardware_profile[manufacturer]',
|
281
|
+
'hwmodel' => 'hardware_profile[model]',
|
282
|
+
'ip' => 'ip_addresses',
|
283
|
+
'ips' => 'ip_addresses',
|
284
|
+
'mac' => 'network_interfaces[hardware_address]',
|
285
|
+
'macs' => 'network_interfaces[hardware_address]',
|
286
|
+
'nic' => 'network_interfaces',
|
287
|
+
'nics' => 'network_interfaces',
|
288
|
+
'node_group' => 'node_group[name]',
|
289
|
+
'node_groups' => 'node_group[name]',
|
290
|
+
'os' => 'operating_system[name]',
|
291
|
+
'osvendor' => 'operating_system[vendor]',
|
292
|
+
'osvariant' => 'operating_system[variant]',
|
293
|
+
'osver' => 'operating_system[version_number]',
|
294
|
+
'osversion' => 'operating_system[version_number]',
|
295
|
+
'osarch' => 'operating_system[architecture]',
|
296
|
+
'serial' => 'serial_number',
|
297
|
+
'status' => 'status[name]',
|
298
|
+
}
|
299
|
+
|
300
|
+
# Convert any shortcut names to their full names
|
301
|
+
if $get
|
302
|
+
$get.each_pair do |key,value|
|
303
|
+
if SEARCH_SHORTCUTS.has_key?(key)
|
304
|
+
$get[SEARCH_SHORTCUTS[key]] = value
|
305
|
+
$get.delete(key)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
if $exactget
|
310
|
+
$exactget.each_pair do |key,value|
|
311
|
+
if SEARCH_SHORTCUTS.has_key?(key)
|
312
|
+
$exactget[SEARCH_SHORTCUTS[key]] = value
|
313
|
+
$exactget.delete(key)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
if $regexget
|
318
|
+
$regexget.each_pair do |key,value|
|
319
|
+
if SEARCH_SHORTCUTS.has_key?(key)
|
320
|
+
$regexget[SEARCH_SHORTCUTS[key]] = value
|
321
|
+
$regexget.delete(key)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
if $exclude
|
326
|
+
$exclude.each_pair do |key,value|
|
327
|
+
if SEARCH_SHORTCUTS.has_key?(key)
|
328
|
+
$exclude[SEARCH_SHORTCUTS[key]] = value
|
329
|
+
$exclude.delete(key)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
if $and
|
334
|
+
$and.each_pair do |key,value|
|
335
|
+
if SEARCH_SHORTCUTS.has_key?(key)
|
336
|
+
$and[SEARCH_SHORTCUTS[key]] = value
|
337
|
+
$and.delete(key)
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
if $set
|
342
|
+
$set.each_pair do |key,value|
|
343
|
+
if SEARCH_SHORTCUTS.has_key?(key)
|
344
|
+
$set[SEARCH_SHORTCUTS[key]] = value
|
345
|
+
$set.delete(key)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
if $allfields
|
350
|
+
# The ideal behavior here is probably debatable. For now I'm _adding_
|
351
|
+
# the expanded value to the list of exclusions, so both the shortcut
|
352
|
+
# string and the expanded value are excluded. That allows the user to
|
353
|
+
# specify 'os' on the command line and get the probably expected behavior
|
354
|
+
# of excluding everything containing 'os' even though 'os' expands to
|
355
|
+
# something specific, but also allows them to specify 'hwmanuf' and have
|
356
|
+
# it exclude the expanded version of that.
|
357
|
+
# Perhaps we should do something like get and exactget?
|
358
|
+
$allfields.each do |key|
|
359
|
+
if SEARCH_SHORTCUTS.has_key?(key)
|
360
|
+
# Replace shortcut with expansion
|
361
|
+
#$allfields[$allfields.index(key)] = SEARCH_SHORTCUTS[key]
|
362
|
+
# Add expansion
|
363
|
+
$allfields << SEARCH_SHORTCUTS[key]
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
if $fields
|
368
|
+
$fields.each do |key|
|
369
|
+
if SEARCH_SHORTCUTS.has_key?(key)
|
370
|
+
$fields[$fields.index(key)] = SEARCH_SHORTCUTS[key]
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
#
|
376
|
+
# Perform requested actions
|
377
|
+
#
|
378
|
+
|
379
|
+
nvclient = NVentory::Client.new($debug, $dryrun, nil, $server)
|
380
|
+
|
381
|
+
# First handle the standalone actions where we perform a single
|
382
|
+
# operation and exit.
|
383
|
+
|
384
|
+
if $getfieldnames
|
385
|
+
field_names = nvclient.get_field_names($objecttype)
|
386
|
+
field_names.each do |field_name_entry|
|
387
|
+
field_name = field_name_entry.split(' ')
|
388
|
+
shortcut = nil
|
389
|
+
shortcut_field_name = nil
|
390
|
+
SEARCH_SHORTCUTS.each_pair do |shortcut, shortcut_field_name|
|
391
|
+
if field_name == shortcut_field_name
|
392
|
+
field_name_entry << " (#{shortcut})"
|
393
|
+
end
|
394
|
+
end
|
395
|
+
puts field_name_entry
|
396
|
+
end
|
397
|
+
exit
|
398
|
+
end
|
399
|
+
if $register
|
400
|
+
nvclient.register
|
401
|
+
exit
|
402
|
+
end
|
403
|
+
if $nodegroup
|
404
|
+
getdata = {}
|
405
|
+
getdata[:objecttype] = 'node_groups'
|
406
|
+
getdata[:exactget] = {'name' => [$nodegroup]}
|
407
|
+
getdata[:includes] = ['child_groups', 'nodes']
|
408
|
+
results = nvclient.get_objects(getdata)
|
409
|
+
matches = results.keys.grep(/\b#{$nodegroup}\b/i)
|
410
|
+
matches.size == 1 ? ( $nodegroup = matches.first ) : return
|
411
|
+
puts "Child groups:"
|
412
|
+
results[$nodegroup]['child_groups'].sort{|a,b| a['name'] <=> b['name']}.each do |child_group|
|
413
|
+
puts " #{child_group['name']}"
|
414
|
+
end
|
415
|
+
puts "===================="
|
416
|
+
puts "Real Nodes:"
|
417
|
+
if results[$nodegroup]['real_nodes_names']
|
418
|
+
results[$nodegroup]['real_nodes_names'].split(",").sort{|a,b| a <=> b}.each do |node|
|
419
|
+
puts " #{node}"
|
420
|
+
end
|
421
|
+
end
|
422
|
+
puts "===================="
|
423
|
+
puts "Virtual Nodes:"
|
424
|
+
if results[$nodegroup]['virtual_nodes_names']
|
425
|
+
results[$nodegroup]['virtual_nodes_names'].split(",").sort{|a,b| a <=> b}.each do |node|
|
426
|
+
puts " #{node}"
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|
430
|
+
if $createnodegroup
|
431
|
+
$createnodegroup.each do |newgroup|
|
432
|
+
nvclient.set_objects('node_groups', nil, {'name' => newgroup}, $username)
|
433
|
+
end
|
434
|
+
exit
|
435
|
+
end
|
436
|
+
if $addnodegrouptonodegroup
|
437
|
+
getdata = {}
|
438
|
+
getdata[:objecttype] = 'node_groups'
|
439
|
+
getdata[:exactget] = {'name' => [$addnodegrouptonodegroup[0]]}
|
440
|
+
child_results = nvclient.get_objects(getdata)
|
441
|
+
abort "Child group '#{$addnodegrouptonodegroup[0]}' not found for 'addnodegrouptonodegroup'\n" if (child_results.length != 1)
|
442
|
+
getdata = {}
|
443
|
+
getdata[:objecttype] = 'node_groups'
|
444
|
+
getdata[:exactget] = {'name' => [$addnodegrouptonodegroup[1]]}
|
445
|
+
getdata[:includes] = ['child_groups']
|
446
|
+
parent_results = nvclient.get_objects(getdata)
|
447
|
+
abort "Parent group '#{$addnodegrouptonodegroup[1]}' not found for 'addnodegrouptonodegroup'\n" if (parent_results.length != 1)
|
448
|
+
nvclient.add_nodegroups_to_nodegroups(child_results, parent_results, $username)
|
449
|
+
exit
|
450
|
+
end
|
451
|
+
if $removenodegroupfromnodegroup
|
452
|
+
getdata = {}
|
453
|
+
getdata[:objecttype] = 'node_groups'
|
454
|
+
getdata[:exactget] = {'name' => [$removenodegroupfromnodegroup[0]]}
|
455
|
+
child_results = nvclient.get_objects(getdata)
|
456
|
+
abort "Child group '#{$removenodegroupfromnodegroup[0]}' not found for 'removenodegroupfromnodegroup'\n" if (child_results.length != 1)
|
457
|
+
getdata = {}
|
458
|
+
getdata[:objecttype] = 'node_groups'
|
459
|
+
getdata[:exactget] = {'name' => [$removenodegroupfromnodegroup[1]]}
|
460
|
+
getdata[:includes] = ['child_groups']
|
461
|
+
parent_results = nvclient.get_objects(getdata)
|
462
|
+
abort "Parent group '#{$removenodegroupfromnodegroup[1]}' not found for 'removenodegroupfromnodegroup'\n" if (parent_results.length != 1)
|
463
|
+
nvclient.remove_nodegroups_from_nodegroups(child_results, parent_results, $username)
|
464
|
+
exit
|
465
|
+
end
|
466
|
+
|
467
|
+
if $createtag
|
468
|
+
$createtag.each do |tag|
|
469
|
+
nvclient.set_objects('tags', nil, {'name' => tag}, $username)
|
470
|
+
end
|
471
|
+
exit
|
472
|
+
end
|
473
|
+
if $addtagtonodegroup
|
474
|
+
getdata = {}
|
475
|
+
getdata[:objecttype] = 'node_groups'
|
476
|
+
getdata[:exactget] = {'name' => [$addtagtonodegroup[1]]}
|
477
|
+
ng_results = nvclient.get_objects(getdata)
|
478
|
+
abort "Node group '#{$addtagtonodegroup[1]}' not found for 'addtagtonodegroup'\n" if (ng_results.length != 1)
|
479
|
+
nvclient.add_tag_to_node_group(ng_results, $addtagtonodegroup[0], $username)
|
480
|
+
exit
|
481
|
+
end
|
482
|
+
if $removetagfromnodegroup
|
483
|
+
getdata = {}
|
484
|
+
getdata[:objecttype] = 'node_groups'
|
485
|
+
getdata[:exactget] = {'name' => [$removetagfromnodegroup[1]]}
|
486
|
+
ng_results = nvclient.get_objects(getdata)
|
487
|
+
abort "Node group '#{$removetagfromnodegroup[1]}' not found for 'removetagfromnodegroup'\n" if (ng_results.length != 1)
|
488
|
+
nvclient.remove_tag_from_node_group(ng_results, $removetagfromnodegroup[0], $username)
|
489
|
+
exit
|
490
|
+
end
|
491
|
+
|
492
|
+
# Now handle the general case where we fetch a list of objects and then
|
493
|
+
# perform operations on them.
|
494
|
+
|
495
|
+
# If the user has requested data which lies outside the base object model
|
496
|
+
# then we need to tell the server to include that data in the results it
|
497
|
+
# sends us.
|
498
|
+
# For example, in a 'nodes' search the user requests the
|
499
|
+
# 'hardware_profile[name]' field then we need to request that
|
500
|
+
# 'hardware_profile' data be included in the results.
|
501
|
+
includes = nil
|
502
|
+
if $fields
|
503
|
+
includes_hash = {}
|
504
|
+
$fields.each do |field|
|
505
|
+
if field =~ /([^\[]+)\[.+\]/
|
506
|
+
includes_hash[$1] = true
|
507
|
+
end
|
508
|
+
end
|
509
|
+
includes = includes_hash.keys.sort
|
510
|
+
elsif $allfields
|
511
|
+
includes_hash = {}
|
512
|
+
field_names = nvclient.get_field_names($objecttype)
|
513
|
+
field_names.each do |field_name_entry|
|
514
|
+
field_name, rest = field_name_entry.split(' ')
|
515
|
+
if field_name =~ /([^\[]+)\[.+\]/
|
516
|
+
includes_hash[$1] = true
|
517
|
+
end
|
518
|
+
end
|
519
|
+
includes = includes_hash.keys.sort
|
520
|
+
end
|
521
|
+
|
522
|
+
results = nil
|
523
|
+
names = nil
|
524
|
+
if $get || $exactget || $regexget
|
525
|
+
$get['enable_aliases'] = 1 if $withaliases
|
526
|
+
getdata = {}
|
527
|
+
getdata[:objecttype] = $objecttype
|
528
|
+
getdata[:get] = $get
|
529
|
+
getdata[:exactget] = $exactget
|
530
|
+
getdata[:regexget] = $regexget
|
531
|
+
getdata[:exclude] = $exclude
|
532
|
+
getdata[:and] = $and
|
533
|
+
if $showtags
|
534
|
+
includes ||= []
|
535
|
+
includes.delete('node_groups') if includes.include?('node_groups')
|
536
|
+
$fields ||= []
|
537
|
+
if $objecttype == 'nodes'
|
538
|
+
$fields << 'node_groups[name]' unless $fields.include?('node_groups[name]')
|
539
|
+
$fields << 'node_groups[tags][name]' unless $fields.include?('node_groups[tags][name]')
|
540
|
+
includes << 'node_groups[tags]' unless includes.include?('node_groups[tags]')
|
541
|
+
elsif $objecttype == 'node_groups'
|
542
|
+
$fields << 'tags[name]' unless $fields.include?('tags[name]')
|
543
|
+
includes << 'tags' unless includes.include?('tags')
|
544
|
+
end
|
545
|
+
end # if $showtags
|
546
|
+
getdata[:includes] = includes
|
547
|
+
results = nvclient.get_objects(getdata)
|
548
|
+
if $delete
|
549
|
+
puts "Deleting objects"
|
550
|
+
nvclient.delete_objects($objecttype, results, $username)
|
551
|
+
else
|
552
|
+
names = results.keys.sort
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
if $addcomment
|
557
|
+
objtype = singularize($objecttype)
|
558
|
+
results.keys.each do |key|
|
559
|
+
nvclient.set_objects('comments', nil,
|
560
|
+
{ 'comment' => $addcomment,
|
561
|
+
'commentable_id' => results[key]['id'],
|
562
|
+
'commentable_type' => objtype.capitalize,
|
563
|
+
},
|
564
|
+
$username);
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
if $nodegroupexpanded
|
569
|
+
names_hash = {}
|
570
|
+
$nodegroupexpanded.each do |nge|
|
571
|
+
nvclient.get_expanded_nodegroup(nge).each { |name| names_hash[name] = true }
|
572
|
+
end
|
573
|
+
names = names_hash.keys.sort
|
574
|
+
if $allfields || $fields || $getallvalues
|
575
|
+
getdata = {}
|
576
|
+
getdata[:objecttype] = 'nodes'
|
577
|
+
getdata[:exactget] = {'name' => names}
|
578
|
+
getdata[:includes] = includes
|
579
|
+
results = nvclient.get_objects(getdata)
|
580
|
+
end
|
581
|
+
end
|
582
|
+
|
583
|
+
if names && !$delete
|
584
|
+
if names.length == 0
|
585
|
+
puts "No matching objects"
|
586
|
+
exit
|
587
|
+
end
|
588
|
+
end
|
589
|
+
|
590
|
+
# The results hash is a complex data structure. This function
|
591
|
+
# does its best to render that in a human readable format.
|
592
|
+
def fieldprint(fields, value)
|
593
|
+
# fields=['name'] => 'name'
|
594
|
+
# fields=['status', 'name'] => 'status[name]'
|
595
|
+
fieldname = ''
|
596
|
+
if fields.length > 0
|
597
|
+
fieldname << fields[0]
|
598
|
+
if fields.length > 1
|
599
|
+
fields[1..-1].each { |f| fieldname << "[#{f}]"}
|
600
|
+
end
|
601
|
+
end
|
602
|
+
|
603
|
+
if value.kind_of?(Hash)
|
604
|
+
value.each_pair do |subfield, subvalue|
|
605
|
+
fieldprint([fields, subfield].flatten, subvalue)
|
606
|
+
end
|
607
|
+
elsif value.kind_of?(Array)
|
608
|
+
value.each do |entry|
|
609
|
+
fieldprint(fields, entry)
|
610
|
+
end
|
611
|
+
elsif ($allfields && !$allfields.any?{|all| fieldname.include?(all)}) || ($fields && $fields.any?{|field| fieldname.include?(field)})
|
612
|
+
puts "#{fieldname}: #{value}"
|
613
|
+
end
|
614
|
+
end
|
615
|
+
|
616
|
+
if names && !$getallvalues && !$set && !$addtonodegroup && !$addnodegroupnodeassignments && !$removefromnodegroup && !$delete
|
617
|
+
names.each do |name|
|
618
|
+
puts name
|
619
|
+
if $allfields || $fields
|
620
|
+
fieldprint([], results[name])
|
621
|
+
puts
|
622
|
+
end
|
623
|
+
end
|
624
|
+
end
|
625
|
+
|
626
|
+
if $getallvalues
|
627
|
+
allvalues = {}
|
628
|
+
|
629
|
+
# FIXME: This is a terribly inefficient implementation
|
630
|
+
# A proper implementation would require something on the
|
631
|
+
# server side to pull this out of the database efficiently
|
632
|
+
names.each do |name|
|
633
|
+
results[name].each_pair do |field,value|
|
634
|
+
if $getallvalues.include?(field)
|
635
|
+
if !allvalues.has_key?(field)
|
636
|
+
allvalues[field] = {}
|
637
|
+
end
|
638
|
+
allvalues[field][value] = true
|
639
|
+
end
|
640
|
+
end
|
641
|
+
end
|
642
|
+
|
643
|
+
$getallvalues.each do |field|
|
644
|
+
puts "#{field}:"
|
645
|
+
allvalues.each_pair do |field,valuehash|
|
646
|
+
valuehash.keys.sort do |value|
|
647
|
+
puts " #{value}"
|
648
|
+
end
|
649
|
+
end
|
650
|
+
puts
|
651
|
+
end
|
652
|
+
end
|
653
|
+
|
654
|
+
if $set
|
655
|
+
if !$yes
|
656
|
+
number_of_matching_entries = names.length
|
657
|
+
entrystring = 'entry'
|
658
|
+
entrystring = 'entries' if (number_of_matching_entries > 1)
|
659
|
+
print "This will update #{number_of_matching_entries} #{entrystring}, continue? [y/N]: "
|
660
|
+
|
661
|
+
input = $stdin.gets
|
662
|
+
if input !~ /^y/i
|
663
|
+
puts "Canceled"
|
664
|
+
exit
|
665
|
+
end
|
666
|
+
end
|
667
|
+
|
668
|
+
nvclient.set_objects($objecttype, results, $set, $username)
|
669
|
+
end
|
670
|
+
|
671
|
+
if $addtonodegroup or $addnodegroupnodeassignments
|
672
|
+
getdata = {}
|
673
|
+
getdata[:objecttype] = 'node_groups'
|
674
|
+
ngnames = $addtonodegroup || $addnodegroupnodeassignments
|
675
|
+
getdata[:exactget] = {'name' => ngnames}
|
676
|
+
if $addtonodegroup
|
677
|
+
getdata[:includes] = ['nodes']
|
678
|
+
end
|
679
|
+
|
680
|
+
nodegroup_results = nvclient.get_objects(getdata)
|
681
|
+
if (nodegroup_results.length != ngnames.length)
|
682
|
+
warn "Not all requested node groups for 'addtonodegroup' were found:"
|
683
|
+
warn "Requested: #{$addtonodegroup.join(',')}"
|
684
|
+
warn "Found: #{nodegroup_results.keys.join(',')}"
|
685
|
+
abort
|
686
|
+
end
|
687
|
+
|
688
|
+
if $addtonodegroup
|
689
|
+
nvclient.add_nodes_to_nodegroups(results, nodegroup_results, $username);
|
690
|
+
elsif $addnodegroupnodeassignments
|
691
|
+
nvclient.add_node_group_node_assignments(results, nodegroup_results, $username);
|
692
|
+
end
|
693
|
+
end
|
694
|
+
|
695
|
+
if $removefromnodegroup
|
696
|
+
getdata = {}
|
697
|
+
getdata[:objecttype] = 'node_groups'
|
698
|
+
getdata[:exactget] = {'name' => $removefromnodegroup}
|
699
|
+
getdata[:includes] = ['nodes']
|
700
|
+
nodegroup_results = nvclient.get_objects(getdata)
|
701
|
+
if (nodegroup_results.length != $removefromnodegroup.length)
|
702
|
+
warn "Not all requested node groups for 'removefromnodegroup' were found:"
|
703
|
+
warn "Requested: #{$removefromnodegroup.join(',')}"
|
704
|
+
warn "Found: #{nodegroup_results.keys.join(',')}"
|
705
|
+
abort
|
706
|
+
end
|
707
|
+
nvclient.remove_nodes_from_nodegroups(results, nodegroup_results, $username);
|
708
|
+
end
|
709
|
+
|