spectools 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. data/CHANGELOG.txt +1 -0
  2. data/Manifest.txt +80 -0
  3. data/README.txt +33 -0
  4. data/README.vnmsh.txt +39 -0
  5. data/Rakefile +42 -0
  6. data/TODO +5 -0
  7. data/lib/spectools.rb +588 -0
  8. data/lib/spectools/version.rb +9 -0
  9. data/lib/vnmsh.rb +1930 -0
  10. data/test/data/connect.success +8 -0
  11. data/test/data/create.alarm +2 -0
  12. data/test/data/create.association +1 -0
  13. data/test/data/create.model +1 -0
  14. data/test/data/create.model.ip +1 -0
  15. data/test/data/destroy.alarm +1 -0
  16. data/test/data/destroy.association +1 -0
  17. data/test/data/destroy.model +9 -0
  18. data/test/data/seek +2 -0
  19. data/test/data/seek.-s +17 -0
  20. data/test/data/show.alarms +10 -0
  21. data/test/data/show.alarms-a +11 -0
  22. data/test/data/show.alarms-a-x +22 -0
  23. data/test/data/show.alarms-x +20 -0
  24. data/test/data/show.alarms.mh +1 -0
  25. data/test/data/show.associations +160 -0
  26. data/test/data/show.attributes +909 -0
  27. data/test/data/show.attributes.attr +2 -0
  28. data/test/data/show.attributes.attriid +2 -0
  29. data/test/data/show.attributes.attrname +6 -0
  30. data/test/data/show.attributes.attrr +14 -0
  31. data/test/data/show.attributes.enum +2 -0
  32. data/test/data/show.attributes.flags +16 -0
  33. data/test/data/show.attributes.mth +242 -0
  34. data/test/data/show.attributes.mth.attrr +12 -0
  35. data/test/data/show.children +47 -0
  36. data/test/data/show.children.rel +14 -0
  37. data/test/data/show.devices +21 -0
  38. data/test/data/show.enumerations +142383 -0
  39. data/test/data/show.enumerations.attr +4 -0
  40. data/test/data/show.enumerations.mth +149 -0
  41. data/test/data/show.events +2001 -0
  42. data/test/data/show.events-a +10001 -0
  43. data/test/data/show.events-n5 +6 -0
  44. data/test/data/show.events-x-n5 +21 -0
  45. data/test/data/show.inheritance +12 -0
  46. data/test/data/show.landscapes +3 -0
  47. data/test/data/show.models +2252 -0
  48. data/test/data/show.models.mhr +18 -0
  49. data/test/data/show.models.mname +4 -0
  50. data/test/data/show.models.mth +4 -0
  51. data/test/data/show.parents +6 -0
  52. data/test/data/show.relations +151 -0
  53. data/test/data/show.rules +5838 -0
  54. data/test/data/show.types +4210 -0
  55. data/test/data/show.types.flags +3137 -0
  56. data/test/data/show.types.mthr +55 -0
  57. data/test/data/show.types.mtname +2 -0
  58. data/test/data/show.watch +9 -0
  59. data/test/data/test.reconnect +1 -0
  60. data/test/data/update.alarm +1 -0
  61. data/test/data/update.model +3 -0
  62. data/test/test_helper.rb +2 -0
  63. data/test/test_spectools.rb +403 -0
  64. data/test/test_vnmsh.rb +1537 -0
  65. data/test/testcmds/ack +1 -0
  66. data/test/testcmds/connect +32 -0
  67. data/test/testcmds/create +34 -0
  68. data/test/testcmds/destroy +36 -0
  69. data/test/testcmds/disconnect +7 -0
  70. data/test/testcmds/seek +18 -0
  71. data/test/testcmds/show +243 -0
  72. data/test/testcmds/update +12 -0
  73. data/test/vnmsh/ack +1 -0
  74. data/test/vnmsh/connect +5 -0
  75. data/test/vnmsh/create +1 -0
  76. data/test/vnmsh/destroy +1 -0
  77. data/test/vnmsh/disconnect +1 -0
  78. data/test/vnmsh/seek +3 -0
  79. data/test/vnmsh/show +1 -0
  80. data/test/vnmsh/update +1 -0
  81. metadata +134 -0
@@ -0,0 +1,9 @@
1
+ module Spectools #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 1
4
+ MINOR = 0
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,1930 @@
1
+ #!/usr/bin/ruby
2
+
3
+ include SpecTools
4
+
5
+ if defined?(SpecTools::Attr)
6
+ class SpecTools::Attr
7
+ #Take a line of CLI <tt>show attributes mh=</tt> output and populate a new Attr object
8
+ def self.cli_parse_mh(line)
9
+ specattr = Attr.new()
10
+ #Because the instance identifier may not fit into the column space allocated, we can't reliably use unpack
11
+ #to parse the data. Instead, we'll use a regex. This means that the attr name can't contain whitespace,
12
+ #but it should be okay.
13
+ if line.chomp =~ /^(\S+)\s+(\S+)\s+(\S+)\s+(.+)$/
14
+ specattr.id = $1
15
+ specattr.name = $2
16
+ specattr.list = true
17
+ specattr.value_table[$3] = $4
18
+ elsif line.chomp =~ /^(\S+)\s+(\S+)\s+(.+)$/
19
+ specattr.id = $1
20
+ specattr.name = $2
21
+ specattr.value = $3
22
+ end
23
+ return specattr
24
+ end
25
+
26
+ #Take a line of CLI <tt>show attributes mth=</tt> output and populate a new Attr object
27
+ def self.cli_parse_mth(line)
28
+ attr = Attr.new
29
+ attr.id,attr.name,attr.type,flags = line.chomp.unpack('A12A33A18A23')
30
+ flags.split(/,/).each do |flag|
31
+ case flag
32
+ when 'E'
33
+ attr.external = true
34
+ when 'R'
35
+ attr.readable = true
36
+ when 'W'
37
+ attr.writeable = true
38
+ when 'S'
39
+ attr.shared = true
40
+ when 'T'
41
+ attr.list = true
42
+ when 'G'
43
+ attr.guaranteed = true
44
+ when 'O'
45
+ attr.global = true
46
+ when 'M'
47
+ attr.memory = true
48
+ when 'D'
49
+ attr.database = true
50
+ when 'P'
51
+ attr.polled = true
52
+ when 'L'
53
+ attr.logged = true
54
+ when 'V'
55
+ attr.preserve = true
56
+ end
57
+ end
58
+ return attr
59
+ end
60
+
61
+ #Use CLI to retrieve the enumerations for the Attr.
62
+ #Returns a new hash of enumerations.
63
+ def cli_get_enums(session=nil)
64
+ unless self.id.hex?
65
+ raise ArgumentError, 'To enumerate this Attr, the Attr must have a valid id.'
66
+ end
67
+ enums = Hash.new
68
+ session = VNMSH.get_session(session)
69
+ enum_output = session.show_enumerations(:attr,self)
70
+ if enum_output != nil
71
+ enum_output.each do |line|
72
+ line.chomp!
73
+ id,str,val = line.unpack('A12A34A12')
74
+ val.sub!(/\s+/, '')
75
+ str.sub!(/\s+$/, '')
76
+ enums[val] = str
77
+ end
78
+ else
79
+ return nil
80
+ end
81
+ return enums
82
+ end
83
+
84
+
85
+ #Execute cli_get_enums and modify the Attr object in place.
86
+ def cli_get_enums!(session=nil)
87
+ new_enums = cli_get_enums(session)
88
+ self.enums = new_enums
89
+ end
90
+
91
+ end
92
+ else
93
+ raise NameError, 'You must require the spectools lib in order to use VNMSH'
94
+ end
95
+
96
+ if defined?(SpecTools::MType)
97
+ class SpecTools::MType
98
+ #Take a line of CLI <tt>show types</tt> output and populate a new MType object.
99
+ def self.cli_parse(line)
100
+ handle,name,flags = line.unpack('A12A1025A11')
101
+ type = MType.new(handle,name)
102
+ flags.chomp.split(/,/).each do |flag|
103
+ case flag
104
+ when 'V'
105
+ type.visible = true
106
+ when 'I'
107
+ type.instantiable = true
108
+ when 'D'
109
+ type.derivable = true
110
+ when 'N'
111
+ type.destroyable = false
112
+ when 'U'
113
+ type.unique = true
114
+ when 'R'
115
+ type.required = true
116
+ end
117
+ end
118
+ return type
119
+
120
+ end
121
+
122
+ #Take a line of CLI <tt>show inheritance</tt> output and populate a new MType object.
123
+ def self.cli_parse_inheritance(line)
124
+ handle,name,flags,inheritance = line.chomp.unpack('A12A18A13A10')
125
+ type = MType.new(handle,name)
126
+ type.inheritance = inheritance
127
+ flags.split(/,/).each do |flag|
128
+
129
+ case flag
130
+ when 'V'
131
+ type.visible = true
132
+ when 'I'
133
+ type.instantiable = true
134
+ when 'D'
135
+ type.derivable = true
136
+ when 'N'
137
+ type.destroyable = false
138
+ when 'U'
139
+ type.unique = true
140
+ when 'R'
141
+ type.required = true
142
+ end
143
+ end
144
+ return type
145
+ end
146
+
147
+ #Use CLI to locate Model Types. Returns an array of MType objects.
148
+ #
149
+ #<tt>filter</tt> is a hash of filter types and thier values.
150
+ #
151
+ #If no filter is passed, returns all MTypes for the connected Landscape.
152
+ #Filter options:
153
+ #
154
+ #* <tt>:flag</tt> - filters on the provided flag
155
+ # * Example: <tt>MType.cli_find({:flag,:unique})</tt>
156
+ #* <tt>:range</tt> - filters on a range of model types
157
+ # * Range can either be a single string, an Array of handles, or an Array of MTypes.
158
+ # * Example: <tt>MType.cli_find({:range,'0x400000-0x500000'})</tt>
159
+ # * Example: <tt>MType.cli_find(:range,['0x400000','0x500000']})</tt>
160
+ #* <tt>:name</tt> - filters on the model type's name (partials accepted)
161
+ # * Example: <tt>MType.cli_find({:name,'VNM'})</tt>
162
+ #* <tt>:landscape</tt> - filters on the given Landscape.
163
+ # * Example: <tt>MType.cli_find({:landscape,'0x400000'})</tt>
164
+ def self.cli_find(filter=nil,session=nil)
165
+ session = VNMSH.get_session(session)
166
+ mtypes = Array.new
167
+ if filter && filter[:flag]
168
+ filter[:flag] = case filter[:flag]
169
+ when :visible then 'V'
170
+ when :instantiable then 'I'
171
+ when :derivable then 'D'
172
+ when :nodestroy then 'N'
173
+ when :unique then 'U'
174
+ when :required then 'R'
175
+ end
176
+ end
177
+ mtype_output = session.show_types(filter)
178
+ mtype_output.each do |line|
179
+ mtypes.push(MType.parse(line))
180
+ end
181
+ return mtypes
182
+ end
183
+
184
+ #Use CLI to retrieve a hash of Attr objects for a given MType.
185
+ #
186
+ #<tt>filter</tt> is a hash of filter types and thier values.
187
+ #
188
+ #If no filter is given, all attributes are returned.
189
+ #
190
+ #Filter options.
191
+ #
192
+ #* <tt>:range</tt> - returns attributes whose ID in in the specified range.
193
+ # * Range can take a single range string, or an array of MType handles or MTypes.
194
+ # * Example: <tt>mtype.cli_get_attrs({:range,['0x10000','0x1000a])</tt>
195
+ # * Example: <tt>mtype.cli_get_attrs({:range,'0x10000-0x1000a'})</tt>
196
+ #* <tt>:name</tt> - returns attributes whose name contains the specified string.
197
+ # * Example: <tt>mtype.cli_get_attrs({:name,'Condition'})</tt>
198
+ #* <tt>:flag</tt> - returns attributes that have the specified flag set.
199
+ # * Example: <tt>mtype.cli_get_attrs({:flag,:global})</tt>
200
+ #* <tt>:landscape</tt> - returns attributes in the specified landscape.
201
+ # * landscape can be a Landscape object or a landscape handle.
202
+ # * Example: <tt>mtype.cli_get_attrs({:landscape,'0x400000'})</tt>
203
+ def cli_get_attrs(filter=nil,session=nil)
204
+ unless self.handle.hex?
205
+ raise ArgumentError, 'Must supply a valid model type handle'
206
+ end
207
+ attrs = Hash.new
208
+ session = VNMSH.get_session(session)
209
+ if filter && filter[:flag]
210
+ flag = case filter[:flag]
211
+ when :external then 'E'
212
+ when :readable then 'R'
213
+ when :writable then 'W'
214
+ when :shared then 'S'
215
+ when :list then 'T'
216
+ when :guaranteed then 'G'
217
+ when :global then 'O'
218
+ when :memory then 'M'
219
+ when :database then 'B'
220
+ when :polled then 'P'
221
+ when :logged then 'L'
222
+ when :preserve then 'V'
223
+ else
224
+ raise ArgumentError, 'Invalid flag'
225
+ end
226
+ filter[:flag] = flag
227
+ end
228
+ attr_output = session.show_attributes(:mtype,self,filter,false)
229
+ attr_output.each do |line|
230
+ tmpattr = Attr.parse_mth(line)
231
+ attrs[tmpattr.id] = tmpattr
232
+ end
233
+ return attrs
234
+ end
235
+
236
+ #Call cli_get_attrs and populate the MType's attrs attribute.
237
+ def cli_get_attrs!(filter=nil,session=nil)
238
+ attrs = self.cli_get_attrs(filter,session)
239
+ self.attrs = attrs
240
+ end
241
+
242
+ #Create a new Model via CLI for this type.
243
+ #attrs is an Array of Attr objects that you want to be set on the
244
+ #model when it is created.
245
+ def cli_create_model(attrs=nil,lh=nil,session=nil)
246
+ session = VNMSH.get_session(session)
247
+ return session.create_model(self,attrs,lh)
248
+ end
249
+
250
+
251
+ end
252
+ else
253
+ raise NameError, 'You must require the spectools lib in order to use VNMSH'
254
+ end
255
+
256
+ if defined?(SpecTools::Model)
257
+ class SpecTools::Model
258
+ #Take a line of CLI <tt>show models</tt> or <tt>seek</tt> output and populate a new Model object.
259
+ def self.cli_parse(line)
260
+ mhandle,mname,mthandle,mtname = line.chomp.unpack('A12A1025A12A20')
261
+ mtype = MType.new(mthandle,mtname)
262
+ model = Model.new(mhandle,mname,mtype)
263
+ return model
264
+ end
265
+
266
+ #Use CLI to locate Models. Returns an array of Model objects.
267
+ #
268
+ #
269
+ #<tt>filter</tt> is a hash of filter types and thier values.
270
+ #
271
+ #If no filter is passed, returns all Models for the connected Landscape.
272
+ #
273
+ #If <tt>devices</tt> is true, returns all devices. In this case,
274
+ #<tt>filter</tt> is ignored.
275
+ #
276
+ #Filter options:
277
+ #
278
+ #* <tt>:range</tt> - filters on a range of models.
279
+ # * Range can either be a single string, an Array of handles, or an Array of Models.
280
+ # * Example: <tt>Model.cli_find({:range,'0x400000-0x500000'})</tt>
281
+ # * Example: <tt>Model.cli_find(:range,['0x400000','0x500000']})</tt>
282
+ #* <tt>:name</tt> - filters on the model's name (partials accepted)
283
+ # * Example: <tt>Model.cli_find({:name,'VNM'})</tt>
284
+ #* <tt>:landscape</tt> - filters on the given Landscape.
285
+ # * Example: <tt>Model.cli_find({:landscape,'0x400000'})</tt>
286
+ #* <tt>:mtype</tt> - Returns all models of the specified type.
287
+ # * Type can either be an MType object, or a model type handle.
288
+ # * Examples:
289
+ # * <tt>Model.cli_find(:mtype, '0x13d0018')</tt>
290
+ # * <tt>Model.cli_find(:mtype, MType.new('0x13d0018'))</tt>
291
+ #
292
+ def self.cli_find(filter=nil,devices=false,session=nil)
293
+ session = VNMSH.get_session(session)
294
+ models = Array.new
295
+ if devices
296
+ if filter && filter[:landscape]
297
+ model_output = session.show_devices(filter[:landscape])
298
+ else
299
+ model_output = session.show_devices
300
+ end
301
+ else
302
+ model_output = session.show_models(filter)
303
+ end
304
+ model_output.each do |line|
305
+ models.push(Model.parse(line))
306
+ end
307
+ return models
308
+ end
309
+
310
+ #Use CLI to locate Models by attribute.
311
+ #
312
+ #<tt>specattr</tt> may be an Attr object or an attribute ID.
313
+ #If <tt>specattr</tt> is an Attr and has the value attribute set,
314
+ #<tt>value</tt> does not have to be set. However, you can override
315
+ #the Attr object's value in the search by providing your own
316
+ #<tt>value</tt>.
317
+ #
318
+ #If <tt>specattr.value</tt> is nil, or of <tt>specattr</tt> is simply
319
+ #an attribute ID, <tt>value</tt> must be set.
320
+ #
321
+ #If <tt>substring</tt> is true, a partial string match is performed.
322
+ #
323
+ #If <tt>nocase</tt> is true, case is ignored.
324
+ #
325
+ def self.cli_find_by_attr(specattr,value=nil,substring=false,nocase=false,session=nil)
326
+ session = VNMSH.get_session(session)
327
+ models = Array.new
328
+ model_output = session.seek(specattr,value,substring,nocase)
329
+ model_output.each do |line|
330
+ models.push(Model.parse(line))
331
+ end
332
+ return models
333
+ end
334
+
335
+ #Use CLI to retrieve a hash of Attr objects for a given Model.
336
+ #
337
+ #<tt>filter</tt> is a hash of filter types and thier values.
338
+ #
339
+ #If no filter is given, all attributes are returned.
340
+ #If <tt>enumerate</tt> is set to true, the values will
341
+ #be automatically enumerated.
342
+ #
343
+ #Filter options.
344
+ #
345
+ #* <tt>:id</tt> - returns the specific attribute.
346
+ # * Takes an Attr or an attribute ID.
347
+ # * Returns all instances for a list attribute.
348
+ # * Example: <tt>model.cli_get_attrs({:id,'0x10000'})</tt>
349
+ #* <tt>:instance</tt> = returns a specific instance of an attribute.
350
+ # * Takes a 2 element array.
351
+ # * The first element must be an Attr or an attribute id.
352
+ # * The second element must be an instance identifier.
353
+ # * Example: <tt>model.cli_get_attrs({:instance,['0x10000','192.168.1.1']})</tt>
354
+ #* <tt>:range</tt> - returns attributes whose ID in in the specified range.
355
+ # * Range can take a single range string, or an array of Model handles or Models.
356
+ # * Example: <tt>model.cli_get_attrs({:range,['0x10000','0x1000a])</tt>
357
+ # * Example: <tt>model.cli_get_attrs({:range,'0x10000-0x1000a'})</tt>
358
+ #* <tt>:name</tt> - returns attributes whose name contains the specified string.
359
+ # * Example: <tt>model.cli_get_attrs({:name,'Condition'})</tt>
360
+ def cli_get_attrs(filter=nil,enumerate=false,session=nil)
361
+ unless self.handle.hex?
362
+ raise ArgumentError, 'Must supply a valid model handle'
363
+ end
364
+ attrs = Hash.new
365
+ session = VNMSH.get_session(session)
366
+
367
+ attr_output = session.show_attributes(:model,self,filter,enumerate)
368
+ attr_output.each do |line|
369
+ tmpattr = Attr.parse_mh(line)
370
+ if attrs[tmpattr.id] && tmpattr.list && attrs[tmpattr.id].value_table
371
+ newiid = tmpattr.value_table.keys.first
372
+ attrs[tmpattr.id].value_table[newiid] =
373
+ tmpattr.value_table[newiid]
374
+ else
375
+ attrs[tmpattr.id] = tmpattr
376
+ end
377
+ end
378
+ return attrs
379
+ end
380
+
381
+ #Use CLI to retreive the children of the current model.
382
+ #Returns an array of Model objects.
383
+ #
384
+ #If <tt>relation</tt> is set to a Relation or a relation
385
+ #name, only parents with the given relation will be
386
+ #retrieved.
387
+ def cli_get_children(relation=nil,session=nil)
388
+ models = Array.new
389
+ session = VNMSH.get_session(session)
390
+ model_output = session.show_children(self,relation)
391
+ model_output.each do |line|
392
+ models.push(Model.parse(line))
393
+ end
394
+ return models
395
+ end
396
+
397
+ #Use CLI to retreive the parents of the current model.
398
+ #Returns an array of Model objects.
399
+ #
400
+ #If <tt>relation</tt> is set to a Relation or a relation
401
+ #name, only parents with the given relation will be
402
+ #retrieved.
403
+ def cli_get_parents(relation=nil,session=nil)
404
+ models = Array.new
405
+ session = VNMSH.get_session(session)
406
+ model_output = session.show_parents(self,relation)
407
+ model_output.each do |line|
408
+ models.push(Model.parse(line))
409
+ end
410
+ return models
411
+ end
412
+
413
+ #Use CLI to retreive the watches of the current model.
414
+ #Returns an array of Watch objects.
415
+ def cli_get_watches(session=nil)
416
+ watches = Array.new
417
+ session = VNMSH.get_session(session)
418
+ watch_output = session.show_watch(self)
419
+ watch_output.each do |line|
420
+ watches.push(SpecTools::Watch.parse(line))
421
+ end
422
+ return watches
423
+ end
424
+
425
+ #Call cli_get_attrs and populate the current Model's attrs attribute.
426
+ #Takes the same arguments as cli_get_attrs
427
+ def cli_get_attrs!(filter=nil,enumerate=false,session=nil)
428
+ attrs = self.cli_get_attrs(filter,enumerate,session)
429
+ self.attrs = attrs
430
+ end
431
+
432
+ #Use CLI to destroy a model.
433
+ #<tt>model</tt> can be either a valid Model, or a model handle.
434
+ def self.cli_destroy(model,session=nil)
435
+ session = VNMSH.get_session(session)
436
+ session.destroy_model(model)
437
+ end
438
+
439
+ #Use CLI to destroy this model.
440
+ def cli_destroy(session=nil)
441
+ self.class.destroy(self.handle,session)
442
+ end
443
+
444
+ #Use CLI to create a new model by IP.
445
+ #
446
+ #Options:
447
+ #* <tt>ip</tt> - Required. The device's IP address.
448
+ #* <tt>community</tt> - Optional. The community string.
449
+ #* <tt>timeout</tt> - Optional. The device's timeout.
450
+ #* <tt>retries</tt> - Optional. The number of times to attempt to contact the device.
451
+ #* <tt>sdm</tt> - Optional. The address of the Secure Domain Connector.
452
+ #* <tt>landscape</tt> - Optional. The landscape to creat the device on.
453
+ #
454
+ def self.cli_discover(ip,community=nil,timeout=nil,retries=nil,sdm=nil,landscape=nil,session=nil)
455
+ session = VNMSH.get_session(session)
456
+ session.discover_device(ip,community,timeout,retries,sdm,landscape)
457
+ end
458
+
459
+ #Use CLI to create a new model.
460
+ #<tt>mtype</tt> may either be a valid MType object, or a model type handle.
461
+ #<tt>attrs</tt> is an array of Attr objects that you want to be set on the
462
+ #model when it is created.
463
+ def self.cli_create(mtype,attrs=nil,lh=nil,session=nil)
464
+ session = VNMSH.get_session(session)
465
+ return session.create_model(mtype,attrs,lh)
466
+ end
467
+
468
+ #Use CLI to update a model's attributes.
469
+ #
470
+ #<tt>attrs</tt> can be a single Attr object, or an array of Attr objects.
471
+ #
472
+ #If <tt>update_model</tt> is true , the attrs of the model will be updated, as well.
473
+ def cli_update_attrs(attrs,update_model = false,session=nil)
474
+ session = VNMSH.get_session(session)
475
+ result = session.update_model(self,attrs)
476
+ if result && update_model
477
+ attrs.each do |specattr|
478
+ self.attrs[specattr.id] = specattr
479
+ end
480
+ end
481
+ return result
482
+ end
483
+
484
+ #Use CLI to associate this model with another.
485
+ #<tt>position</tt> is either <b>:left</b> or <b>:right</b>, and indicates
486
+ #which side of this assocaition the current model will
487
+ #reside.
488
+ #The <tt>model</tt> argument may be a valid Model or a model handle.
489
+ #* Example: <tt>left_model.associate(:left,right_model,relation)</tt>
490
+ def cli_associate(position,model,relation,session = nil)
491
+ session = VNMSH.get_session(session)
492
+ if position == :left
493
+ return session.create_association(relation,self,model)
494
+ elsif position == :right
495
+ return session.create_association(relation,model,self)
496
+ else
497
+ raise ArgumentError, "Valid options are :left or :right"
498
+ end
499
+ end
500
+
501
+ end
502
+ else
503
+ raise NameError, 'You must require the spectools lib in order to use VNMSH'
504
+ end
505
+
506
+ if defined?(SpecTools::Relation)
507
+ class SpecTools::Relation
508
+ #Take a line of CLI <tt>show relations</tt> output and populate a new Relation object.
509
+ def self.cli_parse(line)
510
+ name,type = line.chomp.unpack('A33A15')
511
+ rel = Relation.new(name,type)
512
+ return rel
513
+ end
514
+
515
+ #Use CLI to locate Reltions. Returns an array of Relation objects.
516
+ #
517
+ #If <tt>lanscape</tt> is set to a Landscape or a landscape handle,
518
+ #will only show relations for the given landscape.
519
+ def self.cli_find(landscape=nil,session=nil)
520
+ relations = Array.new
521
+ session = VNMSH.get_session(session)
522
+ rel_output = session.show_relations(landscape)
523
+ rel_output.each do |line|
524
+ relations.push(Relation.parse(line))
525
+ end
526
+ return relations
527
+ end
528
+
529
+ #Retrieve an Array of Rules for the given Relation.
530
+ #
531
+ #If <tt>lanscape</tt> is set to a Landscape or a landscape handle,
532
+ #will only show rules for the given landscape.
533
+ def cli_get_rules(landscape=nil,session=nil)
534
+ session = VNMSH.get_session(session)
535
+ rules = Array.new
536
+ rule_output = session.show_rules(self)
537
+ rule_output.each do |line|
538
+ rules.push(Rule.parse(line))
539
+ end
540
+ return rules
541
+ end
542
+
543
+ #Use CLI to create a new Association based on this Relation.
544
+ #Model arguments may be Model objects or model handles.
545
+ def cli_associate(left_model,right_model,session=nil)
546
+ session = VNMSH.get_session(session)
547
+ return session.create_association(self,left_model,right_model)
548
+ end
549
+
550
+ end
551
+ else
552
+ raise NameError, 'You must require the spectools lib in order to use VNMSH'
553
+ end
554
+
555
+ if defined?(SpecTools::Association)
556
+ class SpecTools::Association
557
+ #Take a line of CLI <tt>show associations</tt> output and populate a new Association object
558
+ def self.parse(line)
559
+ assoc = Association.new()
560
+ lmhandle,lmname,rel,rmhandle,rmname = line.chomp.unpack('A12A1025A33A12A1024')
561
+ assoc.left_model.handle = lmhandle
562
+ assoc.left_model.name = lmname
563
+ assoc.relation.name = rel
564
+ assoc.right_model.handle = rmhandle
565
+ assoc.right_model.name = rmname
566
+ return assoc
567
+ end
568
+
569
+ #Take a line of CLI <tt>show children</tt> output and populate a new Association object
570
+ def self.parse_child(line)
571
+ mhandle,mname,mthandle,mtname,rel = line.chomp.unpack('A12A1025A12A17A31')
572
+ mtype = MType.new(mthandle,mtname)
573
+ model = Model.new(mhandle,mname,mtype)
574
+ relation = Relation.new(rel)
575
+ assoc = Association.new(nil,model,relation)
576
+ return assoc
577
+ end
578
+
579
+ #Take a line of CLI <tt>show parents</tt> output and populate a new Association object
580
+ def self.parse_parent(line)
581
+ mhandle,mname,mthandle,mtname,rel = line.chomp.unpack('A12A1025A12A17A31')
582
+ mtype = MType.new(mthandle,mtname)
583
+ model = Model.new(mhandle,mname,mtype)
584
+ relation = Relation.new(rel)
585
+ assoc = Association.new(model,nil,relation)
586
+ return assoc
587
+ end
588
+
589
+ #Use CLI to destroy a given association.
590
+ #<tt>left_model</tt> and <tt>right_model</tt> may be Model objects or model handles.
591
+ #The <tt>relation</tt> argument may be a Relation or a valid relation name.
592
+ def self.cli_destroy(left_model,right_model,relation,session=nil)
593
+ session = VNMSH.get_session(session)
594
+ session.destroy_association(relation,left_model,right_model)
595
+ end
596
+
597
+ #Use CLI to destroy this association.
598
+ def cli_destroy(session=nil)
599
+ self.class.cli_destroy(left_model,right_model,relation,session)
600
+ end
601
+
602
+ #Use CLI to create a new Association
603
+ #<tt>left_model</tt> and <tt>right_model</tt> may be Model objects or model handles.
604
+ #The <tt>relation</tt> argument may be a Relation or a valid relation name.
605
+ def self.cli_create(relation,left_model,right_model,session = nil)
606
+ session = VNMSH.get_session(session)
607
+ return session.create_association(relation,left_model,right_model)
608
+ end
609
+
610
+
611
+ end
612
+ else
613
+ raise NameError, 'You must require the spectools lib in order to use VNMSH'
614
+ end
615
+
616
+ if defined?(SpecTools::Alarm)
617
+ class SpecTools::Alarm
618
+ #Take a line of CLI <tt>show</tt> output and populate a new Alarm object
619
+ def self.cli_parse(line)
620
+ alarm = Alarm.new
621
+ #OK, here we go. Unfortunately, we have no guidelines to parse this data. It doesn't tend to be fixed-width, and
622
+ #there are no delimteres for a good regex. So, here we have to mix the 2 as best we can.
623
+ #First, we can use a regex to grab out the first few fields.
624
+ line =~ /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/
625
+ alarm.id = $1
626
+ date = $2
627
+ time = $3
628
+ alarm.causeid = $4
629
+ alarm.model.handle = $5
630
+ rest = $6
631
+ month,day,year = date.split(/\//)
632
+ hour,min,sec = time.split(/:/)
633
+ alarm.time = Time.local(year,month,day,hour,min,sec)
634
+ #Alright, now we know that the model name is 1024 characters, so I can grab that with unpack
635
+ alarm.model.name,rest = rest.unpack('A1025A8192')
636
+ #Now, we have to use a regex to extract the model type name, as it will extend and not truncate.
637
+ #We're lucky that Model type names usually don't contain whitespace.
638
+ rest =~ /^(\S+)\s+(.*)$/
639
+ alarm.model.type.name = $1
640
+ rest = $2
641
+ #Now, whether we like it or not, we have to use unpack for the rest
642
+ alarm.severity,ack,stale,alarm.assignment,alarm.status = rest.unpack('A14A4A6A25A4096')
643
+ if ack =~ /Yes/
644
+ alarm.ack = true
645
+ end
646
+ if stale =~ /Yes/
647
+ alarm.stale = true
648
+ end
649
+ return alarm
650
+ end
651
+
652
+ #Use CLI to find Alarms. Returns an array of Alarm objects.
653
+ #Available find types:
654
+ #* <tt>:standard</tt> - Retrieves the standard list of alarms.
655
+ #* <tt>:all</tt> - Retrieves all alarms, including MAINTENANCE.
656
+ #* <tt>:model</tt> - Retrieves standard alarms for a given model.
657
+ # * If set, <tt>mh_or_lh</tt> must be a valid Model or model handle.
658
+ #* <tt>:model</tt> - Identical to :model, except returns all alarms.
659
+ #* <tt>:landscape</tt> - Retrieves standards alarms for a given landscape.
660
+ # * If set, <tt>mh_or_lh</tt> must be a valid Landscape or landscape handle.
661
+ #
662
+ #Setting <tt>probcause</tt> to true will include the Probable Cause
663
+ #information in the <tt>message</tt> attribute of each Alarm.
664
+ def self.cli_find(type=:standard,mh_or_lh=nil,probcause=false,session=nil)
665
+ session = VNMSH.get_session(session)
666
+ alarms = Array.new
667
+ alarm_output = session.show_alarms(type,mh_or_lh,probcause)
668
+ causes = Hash.new
669
+ alarm_output.each do |line|
670
+ if line =~ /\d+\s+\d\d\/\d\d\/\d\d\d\d/
671
+ alarms.push(Alarm.parse(line))
672
+ elsif line =~ /^(0x[a-fA-F0-9]+)\s/
673
+ causeid = $1
674
+ causes[causeid] = line.sub(/^(0x[a-fA-F0-9]+)\s/,"")
675
+ end
676
+ end
677
+ if probcause
678
+ alarms.each do |alarm|
679
+ alarm.message = causes[alarm.causeid]
680
+ end
681
+ end
682
+ return alarms
683
+ end
684
+
685
+ #Use CLI to destroy an alarm.
686
+ def self.cli_destroy(aid,landscape=nil,session=nil)
687
+ session = VNMSH.get_session(session)
688
+ session.destroy_alarm(aid,landscape)
689
+ end
690
+
691
+ #Use CLI to destroy this alarm.
692
+ def cli_destroy(landscape=nil,session=nil)
693
+ self.class.cli_destroy(id,landscape,session)
694
+ end
695
+
696
+ #Use CLI to save all attributes of this alarm.
697
+ def cli_save(session=nil)
698
+ session = VNMSH.get_session(session)
699
+ result = true
700
+ result = session.update_alarm(id, :ticket, ticket, true) && result if ticket != nil
701
+ result = session.update_alarm(id, :assign, assignment, true) && result if assignment != nil
702
+ result = session.update_alarm(id, :status, status, true) && result if status != nil
703
+ result = session.update_alarm(id, :ack, ack) && result if ack != nil
704
+ result = session.update_alarm(id, :url, url, true) && result if url != nil
705
+ result
706
+ end
707
+
708
+ end
709
+ else
710
+ raise NameError, 'You must require the spectools lib in order to use VNMSH'
711
+ end
712
+
713
+ if defined?(SpecTools::Event)
714
+ class SpecTools::Event
715
+ #Take a line of CLI <tt>show</tt> output and populate a new Event object.
716
+ def self.cli_parse(line)
717
+ event = Event.new
718
+ date,time,type,mhandle,mname,mtname,evformat = line.chomp.unpack('A10A12A12A12A1025A15A4096')
719
+ month,day,year = date.split(/\//)
720
+ hour,min,sec = time.split(/:/)
721
+ event.time = Time.local(year,month,day,hour,min,sec)
722
+ event.type = type
723
+ event.model.handle = mhandle
724
+ event.model.name = mname
725
+ event.model.type.name = mtname
726
+ return event
727
+ end
728
+
729
+ #Use CLI to find Events. Returns an array of Event objects. Available find types:
730
+ #* <tt>:all</tt> - Retrieve all events.
731
+ #* <tt>:model</tt> - Retrieve all events for a given model.
732
+ # * If set, mh_or_lh must be a valid Model or a model handle.
733
+ #* <tt>:landscape</tt> - Retrieve all events for a given landscape.
734
+ # * If set, mh_or_lh must be a valid Landscape or a landscape handle.
735
+ #Options:
736
+ #* <tt>limit</tt> - Set the maximum number of events to retrieve.
737
+ # * Default is 2000, Setting to :all is equivalent to setting to 10000
738
+ #* <tt>evformat</tt> - If set to true, populate the Events with the event message.
739
+ def self.cli_find(type=:all,mh_or_lh=nil,limit=2000,evformat=false,session=nil)
740
+ session = VNMSH.get_session(session)
741
+ events = Array.new
742
+ event_output = session.show_events(type,mh_or_lh,limit,evformat)
743
+ event_output.each do |line|
744
+ if line =~ /^\d\d\/\d\d\/\d\d\d\d/
745
+ events.push(Event.parse(line))
746
+ else
747
+ events.last.message = events.last.message + line
748
+ end
749
+ end
750
+ return events
751
+
752
+ end
753
+ end
754
+ else
755
+ raise NameError, 'You must require the spectools lib in order to use VNMSH'
756
+ end
757
+
758
+ if defined?(SpecTools::Rule)
759
+ class SpecTools::Rule
760
+ #Take a line of CLI <tt>show rules</tt> output and populate a new Rule object.
761
+ def self.cli_parse(line)
762
+ line.chomp =~ /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$/
763
+ #lmthandle,lmtname,rmthandle,rmtname = line.chomp.unpack('A12A18A12A18')
764
+ lmthandle = $1
765
+ lmtname = $2
766
+ rmthandle = $3
767
+ rmtname = $4
768
+ lmtype = MType.new(lmthandle,lmtname)
769
+ rmtype = MType.new(rmthandle,rmtname)
770
+ rule = Rule.new(lmtype,rmtype)
771
+ return rule
772
+ end
773
+ end
774
+ else
775
+ raise NameError, 'You must require the spectools lib in order to use VNMSH'
776
+ end
777
+
778
+ if defined?(SpecTools::Watch)
779
+ class SpecTools::Watch
780
+ #Take a line of CLI <tt>show watch</tt> output and populate a new Watch object.
781
+ def self.cli_parse(line)
782
+ id,name,type,status = line.chomp.unpack('A11A33A17A10')
783
+ watch = Watch.new(id,name,type,status)
784
+ return watch
785
+ end
786
+ end
787
+ else
788
+ raise NameError, 'You must require the spectools lib in order to use VNMSH'
789
+ end
790
+
791
+ if defined?(SpecTools::Landscape)
792
+ class SpecTools::Landscape
793
+ #Take a line of CLI <tt>show landscapes</tt> output and populate a new Landscape object.
794
+ def self.cli_parse(line)
795
+ ssname,precedence,port,service,handle = line.chomp.unpack('A33A14A8A12A10')
796
+ landscape = Landscape.new(handle,ssname,precedence,port,service )
797
+ return landscape
798
+ end
799
+
800
+ #Use CLI to retrieve all available landscapes.
801
+ def self.cli_get_landscapes(session=nil)
802
+ session = VNMSH.get_session(session)
803
+ landscapes = Array.new
804
+ lscape_output = session.show_landscapes
805
+ lscape_output.each do |line|
806
+ landscapes.push(Landscape.parse(line))
807
+ end
808
+ return landscapes
809
+ end
810
+ end
811
+ else
812
+ raise NameError, 'You must require the spectools lib in order to use VNMSH'
813
+ end
814
+
815
+ # == SpecTools::VNMSH
816
+ # Represents a CLI session to VNMSH
817
+ class VNMSH
818
+
819
+ #The ID of the connected session.
820
+ attr_reader :session_id
821
+ #The currently connected landscape.
822
+ attr_reader :current_landscape
823
+ #The number of reconncects performed before a command is considered unsuccessful.
824
+ attr_accessor :reconnect_retries
825
+
826
+ class << self
827
+ #The default session to use to execute VNMSH commands.
828
+ attr_accessor :default_session
829
+ end
830
+
831
+ #Create a new VNMSH session. <tt>specroot</tt> is accessed from the SPECROOT
832
+ #environement variable, if no <tt>specroot</tt> is passed.
833
+ def initialize(specroot = nil)
834
+ @vnmshdir = '/vnmsh/'
835
+ vnmshcommands = ['ack','connect','create','destroy','disconnect','seek','show','update']
836
+ if specroot.nil?
837
+ @specroot = ENV['SPECROOT']
838
+ else
839
+ @specroot = specroot
840
+ end
841
+ vnmshcommands.each do |vnmshcommand|
842
+ command = @specroot + @vnmshdir + vnmshcommand
843
+ unless File.exists?(command)
844
+ raise EnvironmentError, "Command #{command} is not available"
845
+ end
846
+ end
847
+ @session_id = rand(20000)
848
+ @connected = false
849
+ @reconnect_retries = 3
850
+ end
851
+
852
+ #Take a parameter check to see if either the session was explictly passed,
853
+ #or if SpecTools::VNMSH#default_session is set.
854
+ #Returns a valid VNMSH object if successful.
855
+ #Raises ArgumentError if no valid VNMSH session is found.
856
+ def self.get_session(arg)
857
+ if arg.instance_of? VNMSH
858
+ return arg
859
+ elsif VNMSH::default_session.instance_of? VNMSH
860
+ return VNMSH::default_session
861
+ else
862
+ raise ArgumentError, 'You must pass a valid session or set SpecTools::VNMSH.default_session to a valid session'
863
+ end
864
+ end
865
+
866
+
867
+ #Connect to the SpectroSERVER
868
+ #If successful, returns a Landscape object indicating what landscape we connected to.
869
+ #Returns a ConnectError if it fails
870
+ def connect(ss = nil, landscape = nil)
871
+ connectcmd = @specroot + '/vnmsh/connect '
872
+ unless ss.nil?
873
+ connectcmd = connectcmd + ss
874
+ end
875
+ connectcmd = connectcmd + ' 2>&1'
876
+ output = StringIO.new(`#{connectcmd}`)
877
+ result = output.readline
878
+ if result =~ /^connect: successful (.*)/
879
+ @current_landscape = Landscape.new()
880
+ @current_landscape.ss = $1
881
+ output.readline =~ /current landscape is (0x\d+)/
882
+ @current_landscape.handle = $1
883
+ @connected = true
884
+ return @current_landscape
885
+ elsif result =~ /^connect: already connected to/
886
+ return @current_landscape
887
+ else
888
+ raise ConnectError, result
889
+ end
890
+ end
891
+
892
+ #Disconnect from the SS. Returns true if the command succeeds,
893
+ #otherwise returns the error string of the disconnect.
894
+ #Either way, session will be marked as disconnected.
895
+ def disconnect
896
+ disconnectcmd = @specroot + '/vnmsh/disconnect 2>&1'
897
+ output = StringIO.new(`#{disconnectcmd}`)
898
+ @connected = false
899
+ result = output.readline
900
+ if result =~ /^disconnect: successful/
901
+ return true
902
+ else
903
+ return result
904
+ end
905
+ end
906
+
907
+ #Execute a VNMSH command.
908
+ #Returns a StringIO object with the command's output.
909
+ #Raises a NotConnectedError if the command exceeds
910
+ #<tt>reconnect_retries</tt>.
911
+ def exec_cmd(cmd)
912
+ @retries = 0
913
+ unless self.connected?
914
+ raise NotConnectedError
915
+ end
916
+ cmd = @specroot + '/vnmsh/' + cmd + ' 2>&1'
917
+ ENV['CLIMNAMEWIDTH'] = 1024.to_s
918
+ ENV['CLISESSID'] = self.session_id.to_s
919
+ begin
920
+ output = `#{cmd}`
921
+ if $?.exitstatus > 0 && StringIO.new(output).readline =~ /Please connect first/
922
+ raise NotConnectedError
923
+ else
924
+ return StringIO.new(output)
925
+ end
926
+ rescue NotConnectedError
927
+ @retries = @retries + 1
928
+ unless @retries > self.reconnect_retries
929
+ self.disconnect
930
+ self.connect
931
+ retry
932
+ else
933
+ raise
934
+ end
935
+ end
936
+
937
+ end
938
+
939
+
940
+
941
+ #Returns true if the session is currently connceted to a SpectroSERVER.
942
+ def connected?
943
+ return @connected
944
+ end
945
+
946
+ #Check to see if the show response returned invalid model or landscape handle.
947
+ def show_invalid_mh_or_lh?(result)
948
+ if result =~ /invalid model handle/
949
+ raise CommandError, result
950
+ elsif result =~ /invalid landscape handle/
951
+ raise CommandError, result
952
+ elsif result =~ /no current model defined/
953
+ raise CommandError, result
954
+ end
955
+ end
956
+
957
+
958
+
959
+ #Execute the <tt>show alarms</tt> command.
960
+ #
961
+ #Available show types:
962
+ #* <tt>:standard</tt> - Retrieves the standard list of alarms.
963
+ #* <tt>:all</tt> - Retrieves all alarms, including MAINTENANCE.
964
+ #* <tt>:model</tt> - Retrieves standard alarms for a given model.
965
+ # * If set, <tt>mh_or_lh</tt> must be a valid Model or model handle.
966
+ #* <tt>:model</tt> - Identical to :model, except returns all alarms.
967
+ #* <tt>:landscape</tt> - Retrieves standards alarms for a given landscape.
968
+ # * If set, <tt>mh_or_lh</tt> must be a valid Landscape or landscape handle.
969
+ #
970
+ #Setting <tt>probcause</tt> to true will include the Probable Cause
971
+ #information in the <tt>message</tt> attribute of each Alarm.
972
+ #
973
+ #Returns a StringIO with the command's ouput.
974
+ def show_alarms(type=:standard,mh_or_lh=nil,probcause=false)
975
+ valid_types = [ :standard,
976
+ :model,
977
+ :model_all,
978
+ :landscape,
979
+ :landscape_all,
980
+ :all ]
981
+ showcmd = 'show alarms '
982
+ valid_type = false
983
+ valid_types.each do |v_type|
984
+ valid_type = v_type || valid_type
985
+ end
986
+
987
+ raise ArgumentError, 'Valid show types are :standard, :all,
988
+ :model, :model_all, :landscape, or :landscape_all' unless valid_type
989
+
990
+ if type == :all || type == :model_all || type == :landscape_all
991
+ showcmd = showcmd + ' -a '
992
+ end
993
+ showcmd = showcmd + ' -x ' if probcause
994
+ if type == :model_all || type == :model
995
+ showcmd += ' mh='
996
+ showcmd = showcmd + get_handle(mh_or_lh,Model)
997
+ end
998
+ if type == :landscape_all || type == :landscape
999
+ showcmd += ' lh='
1000
+ showcmd = showcmd + get_handle(mh_or_lh,Landscape)
1001
+ end
1002
+ output = exec_cmd(showcmd)
1003
+ result = output.readline
1004
+ show_invalid_mh_or_lh?(result)
1005
+ if result =~ /^ID\s+/
1006
+ return output
1007
+ end
1008
+ end
1009
+
1010
+ #Execute the <tt>show models</tt> command.
1011
+ #
1012
+ #If no filter is passed, returns all model listings for the connected Landscape.
1013
+ #
1014
+ #Filter options:
1015
+ #
1016
+ #* <tt>:range</tt> - filters on a range of models.
1017
+ # * Range can either be a single string, an Array of handles, or an Array of Models.
1018
+ # * Example: <tt>show_models({:range,'0x400000-0x500000'})</tt>
1019
+ # * Example: <tt>show_models(:range,['0x400000','0x500000']})</tt>
1020
+ #* <tt>:name</tt> - filters on the model's name (partials accepted)
1021
+ # * Example: <tt>show_models{:name,'VNM'})</tt>
1022
+ #* <tt>:landscape</tt> - filters on the given Landscape.
1023
+ # * Example: <tt>show_models({:landscape,'0x400000'})</tt>
1024
+ #* <tt>:mtype</tt> - Returns all models of the specified type.
1025
+ # * Type can either be an MType object, or a model type handle.
1026
+ # * Examples:
1027
+ # * <tt>show_models(:mtype, '0x13d0018')</tt>
1028
+ # * <tt>show_models(:mtype, MType.new('0x13d0018'))</tt>
1029
+ #
1030
+ #Returns a StringIO with the command's ouput.
1031
+ #
1032
+ def show_models(filter=nil)
1033
+ showcmd = 'show models '
1034
+ if filter
1035
+ filter.keys.each do |option|
1036
+ case option
1037
+ when :range
1038
+ showcmd += ' mhr='
1039
+ showcmd += filter[option] if filter[option].kind_of?(String)
1040
+ showcmd += get_handle(filter[option][0],Model) + '-' +
1041
+ get_handle(filter[option][1],Model) if filter[option].kind_of?(Array)
1042
+ when :type
1043
+ showcmd += ' mth=' + get_handle(filter[option],MType)
1044
+ when :name
1045
+ showcmd += ' mname=' + filter[option]
1046
+ when :landscape
1047
+ showcmd += ' lh=' + get_handle(filter[option],Landscape)
1048
+ else
1049
+ raise ArgumentError, 'Valid filter options are :range, :name, :flag, or :landscape'
1050
+ end
1051
+ end
1052
+ end
1053
+
1054
+ output = self.exec_cmd(showcmd)
1055
+ result = output.readline
1056
+ show_invalid_mh_or_lh?(result)
1057
+ if result =~ /MHandle\s+/
1058
+ return output
1059
+ end
1060
+ end
1061
+
1062
+ #Execute <tt>seek</tt>.
1063
+ #
1064
+ #<tt>specattr</tt> may be an Attr object or an attribute ID.
1065
+ #If <tt>specattr</tt> is an Attr and has the value attribute set,
1066
+ #<tt>value</tt> does not have to be set. However, you can override
1067
+ #the Attr object's value in the search by providing your own
1068
+ #<tt>value</tt>.
1069
+ #
1070
+ #If <tt>specattr.value</tt> is nil, or of <tt>specattr</tt> is simply
1071
+ #an attribute ID, <tt>value</tt> must be set.
1072
+ #
1073
+ #If <tt>substring</tt> is true, a partial string match is performed.
1074
+ #
1075
+ #If <tt>nocase</tt> is true, case is ignored.
1076
+ #
1077
+ #Returns a StringIO with the command's ouput.
1078
+ def seek(specattr,value=nil,substring=false,nocase=false,landscape=nil)
1079
+ seekcmd = 'seek'
1080
+ seekcmd += ' -s' if substring
1081
+ seekcmd += ' -i' if nocase
1082
+ seekcmd += ' attr=' + get_id(specattr,Attr)
1083
+ if specattr.kind_of?(Attr)
1084
+ value = specattr.value unless value
1085
+ end
1086
+ raise ArgumentError, 'When seeking by attribute, must pass in a SpecTools::Attr
1087
+ with a valid value, or an explict attribute value' unless value
1088
+ seekcmd += ',val="' + value + '"'
1089
+ seekcmd += ' lh=' + get_handle(landscape,Landscape) if landscape
1090
+ output = exec_cmd(seekcmd)
1091
+ result = output.readline
1092
+ if result =~ /^MHandle\s+/
1093
+ return output
1094
+ else
1095
+ raise CommandError, result
1096
+ end
1097
+
1098
+ end
1099
+
1100
+
1101
+
1102
+ #Execute <tt>show devices</tt>
1103
+ #
1104
+ #If <tt>landscape</tt> is set, only devices for the
1105
+ #given landscape are gathered.
1106
+ #
1107
+ #Returns a StringIO with the command's ouput.
1108
+ def show_devices(landscape = nil)
1109
+ showcmd = 'show devices '
1110
+ showcmd += ' lh=' + get_handle(landscape,Landscape) if landscape
1111
+ output = self.exec_cmd(showcmd)
1112
+ result = output.readline
1113
+ show_invalid_mh_or_lh?(result)
1114
+ if result =~ /MHandle\s+/
1115
+ return output
1116
+ end
1117
+ end
1118
+
1119
+ #Execute <tt>show types</tt>
1120
+ #
1121
+ #<tt>filter</tt> is a hash of filter types and thier values.
1122
+ #
1123
+ #If no filter is passed, returns all model type listings
1124
+ #for the connected Landscape.
1125
+ #Filter options:
1126
+ #
1127
+ #* <tt>:flag</tt> - filters on the provided flag
1128
+ # * Example: <tt>show_types({:flag,:unique})</tt>
1129
+ #* <tt>:range</tt> - filters on a range of model types
1130
+ # * Range can either be a single string, an Array of handles, or an Array of MTypes.
1131
+ # * Example: <tt>show_types({:range,'0x400000-0x500000'})</tt>
1132
+ # * Example: <tt>show_types(:range,['0x400000','0x500000']})</tt>
1133
+ #* <tt>:name</tt> - filters on the model type's name (partials accepted)
1134
+ # * Example: <tt>show_types({:name,'VNM'})</tt>
1135
+ #* <tt>:landscape</tt> - filters on the given Landscape.
1136
+ # * Example: <tt>show_types({:landscape,'0x400000'})</tt>
1137
+ #
1138
+ #Returns a StringIO with the command's ouput.
1139
+ def show_types(filter=nil)
1140
+ showcmd = 'show types '
1141
+ if filter
1142
+ filter.keys.each do |option|
1143
+ case option
1144
+ when :range
1145
+ showcmd += ' mthr='
1146
+ showcmd += filter[option] if filter[option].kind_of?(String)
1147
+ showcmd += get_handle(filter[option][0],MType) + '-' +
1148
+ get_handle(filter[option][1],MType) if filter[option].kind_of?(Array)
1149
+
1150
+ when :name
1151
+ showcmd += ' mtname=' + filter[option]
1152
+ when :flag
1153
+ showcmd += ' flags=' + filter[option]
1154
+ when :landscape
1155
+ showcmd += ' lh=' + get_handle(filter[option],Landscape)
1156
+ else
1157
+ raise ArgumentError, 'Valid filter options are :range, :name, :flag, or :landscape'
1158
+ end
1159
+ end
1160
+ end
1161
+ output = self.exec_cmd(showcmd)
1162
+ result = output.readline
1163
+ show_invalid_mh_or_lh?(result)
1164
+ if result =~ /Handle\s+/
1165
+ return output
1166
+ end
1167
+ end
1168
+
1169
+ #Execute <tt>show relations</tt>
1170
+ #
1171
+ #If <tt>landscape</tt> is set to a Landscape or a ladnscape handle,
1172
+ #shows relations for the given <tt>landscape</tt>.
1173
+ #
1174
+ #Returns a StringIO with the command's ouput.
1175
+ def show_relations(landscape=nil)
1176
+ showcmd = 'show relations '
1177
+ showcmd += ' lh=' + get_handle(landscape,Landscape) if landscape
1178
+ output = self.exec_cmd(showcmd)
1179
+ result = output.readline
1180
+ show_invalid_mh_or_lh?(result)
1181
+ if result =~ /Name\s+/
1182
+ return output
1183
+ end
1184
+ end
1185
+
1186
+ #Execute <tt>show associations</tt>.
1187
+ #
1188
+ #<tt>mh</tt> can be either a Model, or a model handle.
1189
+ #
1190
+ #Returns a StringIO with the command's ouput.
1191
+ def show_associations(mh)
1192
+ showcmd = 'show associations ' + mh
1193
+ output = self.exec_cmd(showcmd)
1194
+ result = output.readline
1195
+ show_invalid_mh_or_lh?(result)
1196
+ if result =~ /^LMHandle\s+/
1197
+ return output
1198
+ end
1199
+ end
1200
+
1201
+ #Execute <tt>show parents</tt>.
1202
+ #
1203
+ #<tt>model</tt> can be a Model or a model handle.
1204
+ #If <tt>relation</tt> is set to a Relation or a relation
1205
+ #name, only parents with the given relation will be
1206
+ #retrieved.
1207
+ #
1208
+ #Returns a StringIO with the command's ouput.
1209
+ def show_parents(model,relation=nil)
1210
+ showcmd = 'show parents '
1211
+ showcmd += ' rel=' + get_relation(relation) if relation
1212
+ showcmd += ' mh=' + get_handle(model,Model)
1213
+ output = self.exec_cmd(showcmd)
1214
+ result = output.readline
1215
+ show_invalid_mh_or_lh?(result)
1216
+ if result =~ /^MHandle\s+/
1217
+ return output
1218
+ elsif result =~ /invalid relation/
1219
+ raise CommandError, result
1220
+ end
1221
+ end
1222
+
1223
+
1224
+ #Execute <tt>show children</tt>
1225
+ #
1226
+ #<tt>model</tt> can be a Model or a model handle.
1227
+ #If <tt>relation</tt> is set to a Relation or a relation
1228
+ #name, only parents with the given relation will be
1229
+ #retrieved.
1230
+ #
1231
+ #Returns a StringIO with the command's ouput.
1232
+ def show_children(model,relation=nil)
1233
+ showcmd = 'show children '
1234
+ showcmd += ' rel=' + get_relation(relation) if relation
1235
+ showcmd += ' mh=' + get_handle(model,Model)
1236
+ output = self.exec_cmd(showcmd)
1237
+ result = output.readline
1238
+ show_invalid_mh_or_lh?(result)
1239
+ if result =~ /^MHandle\s+/
1240
+ return output
1241
+ elsif result =~ /invalid relation/
1242
+ raise CommandError, result
1243
+ end
1244
+ end
1245
+
1246
+ #Execute <tt>show events</tt>
1247
+ #
1248
+ #Available types:
1249
+ #* <tt>:all</tt> - Retrieve all events.
1250
+ #* <tt>:model</tt> - Retrieve all events for a given model.
1251
+ # * If set, mh_or_lh must be a valid Model or a model handle.
1252
+ #* <tt>:landscape</tt> - Retrieve all events for a given landscape.
1253
+ # * If set, mh_or_lh must be a valid Landscape or a landscape handle.
1254
+ #Options:
1255
+ #* <tt>limit</tt> - Set the maximum number of events to retrieve.
1256
+ # * Default is 2000, Setting to :all is equivalent to setting to 10000
1257
+ #* <tt>evformat</tt> - If set to true, populate the Events with the event message.
1258
+ #
1259
+ #Returns a StringIO with the command's ouput.
1260
+ def show_events(type=:all,mh_or_lh=nil,limit=2000,evformat=false)
1261
+ showcmd = 'show events '
1262
+ if limit == :all
1263
+ showcmd += ' -a '
1264
+ elsif limit != 2000 && limit
1265
+ showcmd += ' -n ' + limit.to_s
1266
+ end
1267
+ if evformat
1268
+ showcmd += ' -x '
1269
+ end
1270
+ if type == :model
1271
+ showcmd += ' mh=' + get_handle(mh_or_lh,Model)
1272
+ end
1273
+ if type == :landscape
1274
+ showcmd += ' lh=' + get_handle(mh_or_lh,Landscape)
1275
+ end
1276
+ output = self.exec_cmd(showcmd)
1277
+ result = output.readline
1278
+ show_invalid_mh_or_lh?(result)
1279
+ if result =~ /^Date\s+/
1280
+ return output
1281
+ end
1282
+ end
1283
+
1284
+ #Execute <tt>show inheritance</tt>
1285
+ #
1286
+ #<tt>mtype</tt> can be an MType or a model type handle.
1287
+ #If <tt>landscape</tt> is set, only gethers inheritance for
1288
+ #the given landscape.
1289
+ #
1290
+ #Returns a StringIO with the command's ouput.
1291
+ def show_inheritance(mtype,landscape = nil)
1292
+ showcmd = 'show inheritance mth=' + get_handle(mtype,MType)
1293
+ showcmd += ' lh=' + get_handle(landscape,Landscape) if landscape
1294
+ output = self.exec_cmd(showcmd)
1295
+ result = output.readline
1296
+ show_invalid_mh_or_lh?(result)
1297
+ if result =~ /^Handle\s+/
1298
+ return output
1299
+ elsif result =~ /invalid model type handle/
1300
+ raise CommandError, result
1301
+ end
1302
+ end
1303
+
1304
+ #Execute <tt>show rules</tt>
1305
+ #
1306
+ #<tt>relation</tt> can be wither a Relation or a relation name.
1307
+ #If <tt>lanscape</tt> is set to a Landscape or a landscape handle,
1308
+ #will only show rules for the given landscape.
1309
+ #
1310
+ #Returns a StringIO with the command's ouput.
1311
+ def show_rules(relation,landscape = nil)
1312
+ showcmd = 'show rules rel=' + get_relation(relation)
1313
+ showcmd += ' lh=' + get_handle(landscape,Landscape) if landscape
1314
+ output = self.exec_cmd(showcmd)
1315
+ result = output.readline
1316
+ show_invalid_mh_or_lh?(result)
1317
+ if result =~ /^LMTHandle\s+/
1318
+ return output
1319
+ elsif result =~ /invalid relation/
1320
+ raise CommandError, result
1321
+ end
1322
+ end
1323
+
1324
+ #Execute <tt>show enumerations</tt>
1325
+ #
1326
+ #Available types are:
1327
+ #
1328
+ #* <b>:mtype</b> - enumerations by model type.
1329
+ # * When set, <tt>mtype_landscape_attr</tt> must be a valid MType or a model type handle.
1330
+ # * May also specify an optional <tt>landscape</tt>, which can be either a Landscape or a landscape handle.
1331
+ #* <b>:landscape</b> - all enumerations for a specific landscape.
1332
+ # * When set, <tt>mtype_landscape_attr</tt> must be a valid Landscape or landscape handle.
1333
+ #* <b>:attr</b> - enumerations for a spceific attribute.
1334
+ # * When set, <tt>mtype_landscape_attr</tt> must be an Attr or an attribute id.
1335
+ #
1336
+ #Returns a StringIO with the command's ouput.
1337
+ def show_enumerations(type=:all,mtype_landscape_attr=nil,landscape=nil)
1338
+ showcmd = 'show enumerations '
1339
+ case type
1340
+ when :mtype
1341
+ showcmd += ' mth=' + get_handle(mtype_landscape_attr,MType)
1342
+ showcmd += ' lh=' + get_handle(landscape,Landscape) if landscape
1343
+ when :landscape
1344
+ showcmd += ' lh=' + get_handle(mtype_landscape_attr,Landscape)
1345
+ when :attr
1346
+ showcmd += ' attr=' + get_id(mtype_landscape_attr,Attr)
1347
+ end
1348
+ output = self.exec_cmd(showcmd)
1349
+ result = output.readline
1350
+ show_invalid_mh_or_lh?(result)
1351
+ if result =~ /Id\s+/
1352
+ return output
1353
+ elsif result =~ /invalid attribute/
1354
+ raise CommandError, result
1355
+ elsif result =~ /invalid model type handle/
1356
+ raise CommandError, result
1357
+ end
1358
+ end
1359
+
1360
+ #Execute <tt>show watch</tt>
1361
+ #
1362
+ #<tt>model</tt> can either be a Model or a model handle.
1363
+ #
1364
+ #Returns a StringIO with the command's ouput.
1365
+ def show_watch(model)
1366
+ showcmd = 'show watch '
1367
+ showcmd += ' mh=' + get_handle(model,Model)
1368
+ output = self.exec_cmd(showcmd)
1369
+ result = output.readline
1370
+ show_invalid_mh_or_lh?(result)
1371
+ if result =~ /^Watch_Id\s+/
1372
+ return output
1373
+ end
1374
+ end
1375
+
1376
+ #Execute <tt>show landscapes</tt>
1377
+ #
1378
+ #Returns a StringIO with the command's ouput.
1379
+ def show_landscapes
1380
+ showcmd = 'show landscapes'
1381
+ output = self.exec_cmd(showcmd)
1382
+ result = output.readline
1383
+ if result =~ /SSName/
1384
+ return output
1385
+ end
1386
+ end
1387
+
1388
+ #Execute <tt>show attributes</tt>
1389
+ #
1390
+ #Available types:
1391
+ #
1392
+ #* <b>:model</b> - Get attributes for a given model.
1393
+ # * When set, mh_or_mth must be a Model or a model handle.
1394
+ # * If <tt>enumerate</tt> is set, values will be automatically enumerated.
1395
+ #* <b>:mtype</b> - get attributes for a given model type.
1396
+ # * When set, mh_or_mth must be a MType or a model type handle.
1397
+ # * <tt>enumerate</tt> is ignored.
1398
+ #
1399
+ #Filter options.
1400
+ #
1401
+ #* <tt>:id</tt> - returns the specific attribute.
1402
+ # * Only valid for the <tt>:model</tt> type.
1403
+ # * Takes an Attr or an attribute ID.
1404
+ # * Returns all instances for a list attribute.
1405
+ # * Example: <tt>show_attributes(:model,{:id,'0x10000'})</tt>
1406
+ #* <tt>:instance</tt> = returns a specific instance of an attribute.
1407
+ # * Only valid for the <tt>:model</tt> type.
1408
+ # * Takes a 2 element array.
1409
+ # * The first element must be an Attr or an attribute id.
1410
+ # * The second element must be an instance identifier.
1411
+ # * Example: <tt>show_attributes(:model,{:instance,['0x10000','192.168.1.1']})</tt>
1412
+ #* <tt>:range</tt> - returns attributes whose ID in in the specified range.
1413
+ # * Valid for both <tt>:model</tt> and <tt>:mtype</tt> types.
1414
+ # * :range can take a single range string, or an array of Model handles or Models.
1415
+ # * Example: <tt>show_attributes(:mtype,{:range,['0x10000','0x1000a])</tt>
1416
+ # * Example: <tt>show_attributes(:model,{:range,'0x10000-0x1000a'})</tt>
1417
+ #* <tt>:name</tt> - returns attributes whose name contains the specified string.
1418
+ # * Valid for both <tt>:model</tt> and <tt>:mtype</tt>.
1419
+ # * Example: <tt>show_attributes(:mtype{:name,'Condition'})</tt>
1420
+ #* <tt>:flag</tt> - returns attributes that have the specified flag set.
1421
+ # * Only valid for the <tt>:mtype</tt> type.
1422
+ # * Example: <tt>show_attributes(:mtype,{:flag,'G'})</tt>
1423
+ #* <tt>:lanscape</tt> - returns attributes in the specified landscape.
1424
+ # * Only valid for the <tt>:mtype</tt> type.
1425
+ # * landscape can be a Landscape object or a landscape handle.
1426
+ # * Example: <tt>show_attributes(:mtype,{:landscape,'0x400000'})</tt>
1427
+ def show_attributes(type,mh_or_mth,filter=nil,enumerate=false)
1428
+ showcmd = 'show attributes '
1429
+ if type == :model
1430
+ showcmd += ' -e ' if enumerate
1431
+ if filter
1432
+ filter.keys.each do |option|
1433
+ case option
1434
+ when :id
1435
+ showcmd += ' attr=' + get_id(filter[option],Attr)
1436
+ when :instance
1437
+ if filter[option].kind_of?(Attr)
1438
+ instance = filter[option].instance
1439
+ attrid = filter[option].id
1440
+ else
1441
+ instance = filter[option][1]
1442
+ attrid = filter[option][0]
1443
+ end
1444
+ raise ArgumentError, 'instance is not an instance identifier' unless
1445
+ instance =~ /^\d+(\.\d+)*$/
1446
+ showcmd += ' attr=' + get_id(attrid,Attr) + ',iid=' + instance
1447
+ when :name
1448
+ showcmd += ' attrname=' + filter[option]
1449
+ when :range
1450
+ showcmd += ' attrr='
1451
+ showcmd += filter[option] if filter[option].kind_of?(String)
1452
+ showcmd += get_id(filter[option][0],Attr) + '-' +
1453
+ get_id(filter[option][1],Attr) if filter[option].kind_of?(Array)
1454
+ end
1455
+ end
1456
+ end
1457
+ showcmd += ' mh=' + get_handle(mh_or_mth,Model)
1458
+ elsif type == :mtype
1459
+ showcmd += ' mth=' + get_handle(mh_or_mth,MType)
1460
+ if filter
1461
+ filter.keys.each do |option|
1462
+ case option
1463
+ when :range
1464
+ showcmd += ' attrr='
1465
+ showcmd += filter[option] if filter[option].kind_of?(String)
1466
+ showcmd += get_id(filter[option][0],Attr) + '-' +
1467
+ get_id(filter[option][1],Attr) if filter[option].kind_of?(Array)
1468
+ when :name
1469
+ showcmd += ' attrname=' + filter[option]
1470
+ when :flag
1471
+ showcmd += ' flags=' + filter[option]
1472
+ when :landscape
1473
+ showcmd += ' lh=' + get_handle(filter[option],Landscape)
1474
+ end
1475
+ end
1476
+ end
1477
+ else
1478
+ raise ArgumentError, 'Valid types are :model or :mtype'
1479
+ end
1480
+ output = self.exec_cmd(showcmd)
1481
+ result = output.readline
1482
+ show_invalid_mh_or_lh?(result)
1483
+ if result =~ /^Id\s+/
1484
+ return output
1485
+ elsif result =~ /invalid model type handle/
1486
+ raise CommandError, result
1487
+ elsif result =~ /non list attribute/
1488
+ raise CommandError, result
1489
+ elsif result =~ /invalid attribute/
1490
+ raise CommandError,result
1491
+ elsif result =~ /invalid instance/
1492
+ raise CommandError,result
1493
+ end
1494
+ end
1495
+
1496
+ #Execute <tt>destroy model</tt>.
1497
+ #
1498
+ #<tt>model</tt> can either be a Model or a model handle
1499
+ #
1500
+ #Returns true if the destroy succeeded, otherwise CommandError
1501
+ #is raised.
1502
+ def destroy_model(model)
1503
+ destroycmd = 'destroy model -n mh=' + get_handle(model,Model)
1504
+ output = exec_cmd(destroycmd)
1505
+ result = output.readlines.last
1506
+ if result =~ /destroy model: successful/
1507
+ return true
1508
+ else
1509
+ raise CommandError, result
1510
+ end
1511
+ end
1512
+
1513
+ #Execute <tt>destroy association</tt>.
1514
+ #
1515
+ #Returns true if the destroy succeeded, otherwise CommandError
1516
+ #is raised.
1517
+ def destroy_association(relation,left_model,right_model)
1518
+ destroycmd = 'destroy association -n '
1519
+ destroycmd += ' rel=' + get_relation(relation)
1520
+ destroycmd += ' lmh=' + get_handle(left_model,Model)
1521
+ destroycmd += ' rmh=' + get_handle(right_model,Model)
1522
+ output = exec_cmd(destroycmd)
1523
+ result = output.readlines.last
1524
+ if result =~ /destroy association: successful/
1525
+ return true
1526
+ else
1527
+ raise CommandError, result
1528
+ end
1529
+ end
1530
+
1531
+ #Execute <tt>destroy alarm</tt>
1532
+ #
1533
+ #<tt>alarm</tt> can be an Alarm or an alarm ID.
1534
+ #
1535
+ #If <tt>landscape</tt> is set, will detroy the alarm
1536
+ #on the specified landscape.
1537
+ #<tt>landscape</tt> can be a Landscape object or a valid
1538
+ #landscape handle.
1539
+ #
1540
+ #Returns true if the destroy succeeded, otherwise CommandError
1541
+ #is raised.
1542
+ def destroy_alarm(alarm,landscape=nil)
1543
+ destroycmd = 'destroy alarm -n aid=' + get_id(alarm,Alarm)
1544
+ destroycmd += ' lh=' + get_handle(landscape,Landscape) if landscape
1545
+ output = exec_cmd(destroycmd)
1546
+ result = output.readlines.last
1547
+ if result =~ /destroy alarm: successful/
1548
+ return true
1549
+ else
1550
+ raise CommandError, result
1551
+ end
1552
+ end
1553
+
1554
+ #Execute <tt>create model</tt> with the IP
1555
+ #option.
1556
+ #
1557
+ #Options:
1558
+ #* <tt>ip</tt> - Required. The device's IP address.
1559
+ #* <tt>comm</tt> - Optional. The community string.
1560
+ #* <tt>timeout</tt> - Optional. The device's timeout.
1561
+ #* <tt>retries</tt> - Optional. The number of times to attempt to contact the device.
1562
+ #* <tt>sdm</tt> - Optional. The address of the Secure Domain Connector.
1563
+ #* <tt>landscape</tt> - Optional. The landscape to create the device on.
1564
+ #
1565
+ #If creation is sucessful, returns a new Model with the handle filled in.
1566
+ #otherwise, raises a CommandError.
1567
+ def discover_device(ip,comm=nil,timeout=nil,retries=nil,sdm=nil,landscape=nil)
1568
+ createcmd = 'create model ip=' + ip
1569
+ createcmd += ' sec_dom=' + sdm if sdm
1570
+ createcmd += ' comm=' + comm if comm
1571
+ createcmd += ' to=' + timeout if timeout
1572
+ createcmd += ' tc=' + retries if retries
1573
+ createcmd += ' lh=' + get_handle(landscape,Landscape) if landscape
1574
+ output = exec_cmd(createcmd)
1575
+ result = output.readlines.last
1576
+ if result =~ /created model handle\s+=\s+(0x[0-f]+)/
1577
+ model = Model.new
1578
+ model.handle = $1
1579
+ return model
1580
+ else
1581
+ raise CommandError, result
1582
+ end
1583
+ end
1584
+
1585
+ #Execute <tt>create model</tt> without the
1586
+ #IP option.
1587
+ #<tt>mtype</tt> may either be a valid MType object, or a model type handle.
1588
+ #<tt>attrs</tt> is an array of Attr objects that you want to be set on the
1589
+ #model when it is created.
1590
+ #<tt>landscape</tt> is the landscape you wish to create the model on.
1591
+ #<tt>landscape</tt> may be a Landscape object or a landscape handle.
1592
+ def create_model(mtype,attrs=nil,landscape=nil)
1593
+ createcmd = 'create model mth='
1594
+ createcmd += get_handle(mtype,MType)
1595
+ createcmd += expand_attrs(attrs) if attrs
1596
+ createcmd += ' lh=' + get_handle(landscape,Landscape) if landscape
1597
+ output = exec_cmd(createcmd)
1598
+ result = output.readlines.last
1599
+ if result =~ /created model handle\s+=\s+(0x[0-f]+)/
1600
+ model = Model.new
1601
+ model.handle = $1
1602
+ model.attrs = attrs
1603
+ if mtype.instance_of?(MType)
1604
+ model.type = mtype
1605
+ else
1606
+ model.type = MType.new(mtype)
1607
+ end
1608
+ return model
1609
+ else
1610
+ raise CommandError, result
1611
+ end
1612
+
1613
+ end
1614
+
1615
+ #Execute <tt>update model</tt>.
1616
+ #<tt>model</tt> can be a Model object or a model handle.
1617
+ #<tt>attrs</tt> is an array of Attr objects to update.
1618
+ #
1619
+ #Returns true if the update succeeded, or raises a CommandError.
1620
+ def update_model(model,attrs)
1621
+ updatecmd = 'update mh='
1622
+ updatecmd += get_handle(model,Model)
1623
+ updatecmd += expand_attrs(attrs)
1624
+ output = exec_cmd(updatecmd)
1625
+ result = output.readlines.first
1626
+ if result =~ /^Id/
1627
+ return true
1628
+ else
1629
+ raise CommandError, result
1630
+ end
1631
+ end
1632
+
1633
+ #Execute <tt>update alarm</tt>.
1634
+ #<tt>alarm</tt> can be an Alarm object or an alarm id.
1635
+ #<tt>action</tt> is the field that will be updated.
1636
+ #Valid actions are:
1637
+ #* <tt>:assign</tt>
1638
+ #* <tt>:ticket</tt>
1639
+ #* <tt>:url</tt>
1640
+ #* <tt>:ack</tt>
1641
+ #* <tt>:status</tt>
1642
+ #
1643
+ #<tt>action</tt> may also be a Hash of alarm attributes to set.
1644
+ #If <tt>action</tt> is a single attribute, <tt>value</tt> must be set.
1645
+ #<tt>replace</tt> will replace the existing value, as opposed to just
1646
+ #appending. <tt>replace</tt> is only valid when updating <tt>:ticket</tt>
1647
+ #and <tt>status</tt>.
1648
+ #
1649
+ def update_alarm(alarm,action,val=nil,replace=false)
1650
+ if action.kind_of?(Symbol) && val == nil
1651
+ raise ArgumentError, 'When updating an individual alarm attribute, you must pass a value'
1652
+ elsif action.kind_of?(Hash) && replace == true
1653
+ raise ArgumentError, 'Field replacement may only be done by updating a single alarm attribute'
1654
+ end
1655
+ unless action.kind_of?(Hash) || action.kind_of?(Symbol)
1656
+ raise ArgnumentError, 'Valid actions may be a single Symbol or a Hash'
1657
+ end
1658
+ updatecmd = 'update alarm aid='
1659
+ if alarm.instance_of?(Alarm)
1660
+ updatecmd += alarm.id
1661
+ else
1662
+ updatecmd += alarm
1663
+ end
1664
+ if action.kind_of?(Symbol)
1665
+ updatecmd += ' -r ' if replace
1666
+ updatecmd += process_alarm_action(action,val)
1667
+ end
1668
+ if action.kind_of?(Hash)
1669
+ action.keys.each do |key|
1670
+ updatecmd += process_alarm_action(key,action[key])
1671
+ end
1672
+ end
1673
+ result = exec_cmd(updatecmd)
1674
+ if $?.exitstatus == 0
1675
+ return true
1676
+ else
1677
+ raise CommandError, result
1678
+ end
1679
+ end
1680
+
1681
+
1682
+
1683
+
1684
+ #Execute <tt>create association</tt>.
1685
+ #
1686
+ #<tt>relation</tt> can be a Relation object or a relation name.
1687
+ #<tt>left_model</tt> and <tt>right_model</tt> can be a
1688
+ #Model object or a model handle.
1689
+ def create_association(relation,left_model,right_model)
1690
+ createcmd = 'create association '
1691
+ createcmd += ' rel=' + get_relation(relation)
1692
+ createcmd += ' lmh='
1693
+ createcmd += get_handle(left_model,Model)
1694
+ createcmd += ' rmh='
1695
+ createcmd += get_handle(right_model,Model)
1696
+
1697
+ output = exec_cmd(createcmd)
1698
+ result = output.readlines.last
1699
+ if result =~ /create association: successful/
1700
+ if relation.kind_of? String
1701
+ rel = Relation.new(rel)
1702
+ end
1703
+ if left_model.kind_of? String
1704
+ left_model = Model.new(left_model)
1705
+ end
1706
+ if right_model.kind_of? String
1707
+ right_model = Model.new(right_model)
1708
+ end
1709
+ return Association.new(left_model,right_model,relation)
1710
+ else
1711
+ raise CommandError, result
1712
+ end
1713
+ end
1714
+
1715
+ #Execute <tt>create alarm</tt>.
1716
+ #* <tt>severity</tt> is the alarm severity. Allowable options are:
1717
+ # * CRITICAL
1718
+ # * MAJOR
1719
+ # * MINOR
1720
+ # * SUPPRESSED
1721
+ # * MAINTENANCE
1722
+ # * INITIAL
1723
+ #* <tt>cause</tt> is the probable cause code.
1724
+ #* <tt>model</tt> is the model to assert the alarm on.
1725
+ # * <tt>model</tt> can be a Model object or a model handle.
1726
+ #* If <tt>replace</tt> is true, will replace an existing alarm on the model.
1727
+ #
1728
+ #Returns the created Alarm object if sucessful, otherwise raises a CommandError.
1729
+ def create_alarm(severity,cause,model,replace = false)
1730
+ createcmd = 'create alarm '
1731
+ createcmd += '-nr ' if replace
1732
+ if severity =~ /CRITICAL/i ||
1733
+ /MAJOR/i ||
1734
+ /MINOR/i ||
1735
+ /SUPPRESSED/i ||
1736
+ /MAINTENANCE/i ||
1737
+ /INITIAL/i
1738
+ createcmd += "sev=#{severity} "
1739
+ else
1740
+ raise ArgumentError, 'Severity must be CRITICAL, MAJOR, MINOR, SUPPRESSED, MAINTENANCE, or INITIAL'
1741
+ end
1742
+ if cause.instance_of?(Alarm)
1743
+ createcmd += "cause=#{cause.causeid} "
1744
+ elsif cause.kind_of?(String)
1745
+ createcmd += "cause=#{cause} "
1746
+ else
1747
+ raise ArgumentError, 'You must pass a valid Probable Cause code'
1748
+ end
1749
+ createcmd += 'mh='+get_handle(model,Model)
1750
+ output = exec_cmd(createcmd).readlines
1751
+ if output.first =~ /^ID/
1752
+ return Alarm.parse(output.last)
1753
+ else
1754
+ raise CommandError, output.last
1755
+ end
1756
+ end
1757
+
1758
+ #Execute <tt>create event</tt>.
1759
+ #
1760
+ #<tt>model</tt> can be a Model or a model handle.
1761
+ #<tt>evcode</tt> is a valid event code.
1762
+ #<tt>text</tt> is the event text.
1763
+ #
1764
+ #Returns true if the event was created, otherwise returns
1765
+ #a CommandError.
1766
+ #
1767
+ def create_event(model,evcode,text='')
1768
+ createcmd = 'create event type='
1769
+ if evcode.instance_of?(Event)
1770
+ createcmd += evcode.type
1771
+ createcmd += ' text=\"' + evcode.message + '\"'
1772
+ elsif evcode.kind_of?(String) && evcode.hex?
1773
+ createcmd += evcode
1774
+ createcmd += ' text=\"' + text + '\"'
1775
+ else
1776
+ raise ArgumentError, 'You must pass a valid Event Code'
1777
+ end
1778
+ createcmd += ' mh=' + get_handle(model,Model)
1779
+ output = exec_cmd(createcmd)
1780
+ if $?.exitstatus > 0
1781
+ raise CommandError, output.readlines.first
1782
+ else
1783
+ return true
1784
+ end
1785
+ end
1786
+
1787
+
1788
+
1789
+
1790
+
1791
+
1792
+
1793
+
1794
+
1795
+ private
1796
+
1797
+ def valid_alarm_action?(action)
1798
+ validactions = [ :ticket,
1799
+ :assign,
1800
+ :status,
1801
+ :ack,
1802
+ :url ]
1803
+ ret = false
1804
+ validactions.each do |validaction|
1805
+ if action == validaction
1806
+ ret=true
1807
+ end
1808
+ end
1809
+ return ret
1810
+ end
1811
+
1812
+ def process_alarm_action(action,value)
1813
+ if valid_alarm_action?(action)
1814
+ return ' ' + action.to_s + '="' + value.to_s + '"'
1815
+ else
1816
+ raise ArgumentError, 'The requested field to update, ' + action.to_s + ', is not valid'
1817
+ end
1818
+ end
1819
+
1820
+
1821
+ def get_handle(obj,match_class)
1822
+ if obj.instance_of?(match_class)
1823
+ raise ArgumentError, match_class.to_s + ' must have a valid handle.' unless obj.handle && obj.handle.hex?
1824
+ return obj.handle
1825
+ elsif obj.kind_of?(String) && obj.hex?
1826
+ return obj
1827
+ else
1828
+ raise ArgumentError, 'Argument must be a ' + match_class.to_s + ' object or a valid handle.'
1829
+ end
1830
+ end
1831
+
1832
+ def get_id(obj,match_class)
1833
+ if obj.instance_of?(match_class)
1834
+ formaterror = match_class.to_s + ' must have a valid id.'
1835
+ if obj.instance_of?(Alarm)
1836
+ raise ArgumentError, formaterror unless obj.id == obj.id.to_i.to_s
1837
+ else
1838
+ raise ArgumentError, formaterror unless obj.id && obj.id.hex?
1839
+ end
1840
+ return obj.id
1841
+ elsif (obj.kind_of?(String) && obj.hex? && match_class != Alarm) ||
1842
+ (match_class == Alarm && obj.to_s == obj.to_i.to_s)
1843
+ return obj
1844
+ else
1845
+ raise ArgumentError, 'Argument must be a ' + match_class.to_s + ' object or a valid id.'
1846
+ end
1847
+ end
1848
+
1849
+ def get_relation(rel)
1850
+ if rel.instance_of?(Relation)
1851
+ raise ArgumentError, 'Relation must have a valid name.' unless rel.name
1852
+ return rel.name
1853
+ else
1854
+ return rel
1855
+ end
1856
+ end
1857
+
1858
+ def expand_attr(specattr,instance=nil)
1859
+ unless specattr.instance_of?(Attr)
1860
+ raise ArgumentError, 'Argument must be a SpecTools::Attr'
1861
+ end
1862
+ str = ' attr=' + specattr.id
1863
+ if specattr.list
1864
+ if specattr.value_table && spceattr.value_table[instance]
1865
+ str += ',iid=' + instance
1866
+ val = value_table[instance]
1867
+ else
1868
+ raise IsAListAttrError, 'Attempt to update a list attribute without an instance'
1869
+ end
1870
+ else
1871
+ val = specattr.value
1872
+ end
1873
+ str += ',val="' + val + '"'
1874
+
1875
+ end
1876
+
1877
+ def expand_attrs(attrs)
1878
+ cmd=''
1879
+ if attrs.kind_of?(Array)
1880
+ attrs.each do |specattr|
1881
+ cmd += expand_attr(specattr)
1882
+ end
1883
+ else
1884
+ cmd += expand_attr(attrs)
1885
+ end
1886
+ return cmd
1887
+ end
1888
+
1889
+ def append_lh(cmd,landscape)
1890
+ if landscape.instance_of?(Landscape)
1891
+ cmd += ' lh=' + landscape.handle
1892
+ elsif landscape.kind_of?(String) && landscape.hex?
1893
+ cmd += ' lh=' + landscape
1894
+ end
1895
+ end
1896
+
1897
+
1898
+
1899
+
1900
+
1901
+
1902
+ public
1903
+
1904
+ # == SpecTools::EnvironmentError
1905
+ # This error means that the module was unable to detect a proper environment for VNMSH.
1906
+ # Possible causes might be that the Specroot passwed was invalid, or the user does not
1907
+ # have execute permissions to the VNMSH commands.
1908
+ class EnvironmentError < StandardError
1909
+ end
1910
+
1911
+ # == SpecTools::ConnectError
1912
+ # This error means that the module was unable to connect to a SpectroSERVER.
1913
+ class ConnectError < StandardError
1914
+ end
1915
+
1916
+ # == SpecTools::NotConnectedError
1917
+ # This error means that you attempted to use a session that was not yet connected.
1918
+ class NotConnectedError < StandardError
1919
+ end
1920
+
1921
+ # == SpecTools::CommandError
1922
+ # This error means that the attempted command failed to execute
1923
+ class CommandError < StandardError
1924
+ end
1925
+
1926
+ end
1927
+
1928
+
1929
+
1930
+