acirb 1.0.4h
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.
- checksums.yaml +7 -0
- data/lib/acirb/aaa.rb +1477 -0
- data/lib/acirb/ac.rb +133 -0
- data/lib/acirb/action.rb +533 -0
- data/lib/acirb/actrl.rb +1269 -0
- data/lib/acirb/actrlcap.rb +37 -0
- data/lib/acirb/adcom.rb +421 -0
- data/lib/acirb/aib.rb +85 -0
- data/lib/acirb/arp.rb +309 -0
- data/lib/acirb/bfd.rb +245 -0
- data/lib/acirb/bgp.rb +1109 -0
- data/lib/acirb/callhome.rb +373 -0
- data/lib/acirb/cap.rb +101 -0
- data/lib/acirb/cdp.rb +325 -0
- data/lib/acirb/cnw.rb +101 -0
- data/lib/acirb/comm.rb +2981 -0
- data/lib/acirb/comp.rb +3285 -0
- data/lib/acirb/compat.rb +613 -0
- data/lib/acirb/condition.rb +213 -0
- data/lib/acirb/config.rb +261 -0
- data/lib/acirb/coop.rb +709 -0
- data/lib/acirb/copp.rb +645 -0
- data/lib/acirb/ctrlr.rb +37 -0
- data/lib/acirb/ctx.rb +101 -0
- data/lib/acirb/datetime.rb +389 -0
- data/lib/acirb/dbg.rb +1397 -0
- data/lib/acirb/dbgac.rb +757 -0
- data/lib/acirb/dbgexp.rb +661 -0
- data/lib/acirb/dhcp.rb +1141 -0
- data/lib/acirb/dhcptlv.rb +133 -0
- data/lib/acirb/dhcptlvpol.rb +133 -0
- data/lib/acirb/dlgt.rb +21 -0
- data/lib/acirb/dns.rb +293 -0
- data/lib/acirb/draw.rb +37 -0
- data/lib/acirb/edr.rb +85 -0
- data/lib/acirb/eigrp.rb +789 -0
- data/lib/acirb/ep.rb +69 -0
- data/lib/acirb/epm.rb +133 -0
- data/lib/acirb/eptrk.rb +117 -0
- data/lib/acirb/eqpt.rb +6405 -0
- data/lib/acirb/eqptcap.rb +197 -0
- data/lib/acirb/eqptcapacity.rb +4069 -0
- data/lib/acirb/eqptdiag.rb +181 -0
- data/lib/acirb/eqptdiagp.rb +981 -0
- data/lib/acirb/ethpm.rb +309 -0
- data/lib/acirb/event.rb +197 -0
- data/lib/acirb/extnw.rb +181 -0
- data/lib/acirb/fabric.rb +6693 -0
- data/lib/acirb/fault.rb +821 -0
- data/lib/acirb/file.rb +149 -0
- data/lib/acirb/firmware.rb +645 -0
- data/lib/acirb/fmcast.rb +101 -0
- data/lib/acirb/frmwrk.rb +277 -0
- data/lib/acirb/fsm.rb +21 -0
- data/lib/acirb/fv.rb +6901 -0
- data/lib/acirb/fvcap.rb +37 -0
- data/lib/acirb/fvns.rb +533 -0
- data/lib/acirb/fvtopo.rb +85 -0
- data/lib/acirb/geo.rb +133 -0
- data/lib/acirb/glean.rb +85 -0
- data/lib/acirb/ha.rb +21 -0
- data/lib/acirb/health.rb +341 -0
- data/lib/acirb/hvs.rb +357 -0
- data/lib/acirb/icmp.rb +69 -0
- data/lib/acirb/icmpv4.rb +69 -0
- data/lib/acirb/icmpv6.rb +85 -0
- data/lib/acirb/ident.rb +693 -0
- data/lib/acirb/igmp.rb +69 -0
- data/lib/acirb/igmpsnoop.rb +293 -0
- data/lib/acirb/im.rb +117 -0
- data/lib/acirb/imginstall.rb +21 -0
- data/lib/acirb/infra.rb +3893 -0
- data/lib/acirb/ip.rb +389 -0
- data/lib/acirb/ipmcsnoop.rb +293 -0
- data/lib/acirb/ipv4.rb +133 -0
- data/lib/acirb/ipv6.rb +149 -0
- data/lib/acirb/isis.rb +1653 -0
- data/lib/acirb/isistlv.rb +133 -0
- data/lib/acirb/l1.rb +741 -0
- data/lib/acirb/l1cap.rb +37 -0
- data/lib/acirb/l2.rb +2437 -0
- data/lib/acirb/l2cap.rb +37 -0
- data/lib/acirb/l2ext.rb +309 -0
- data/lib/acirb/l3.rb +613 -0
- data/lib/acirb/l3cap.rb +37 -0
- data/lib/acirb/l3ext.rb +949 -0
- data/lib/acirb/l3vm.rb +53 -0
- data/lib/acirb/l4.rb +53 -0
- data/lib/acirb/lacp.rb +293 -0
- data/lib/acirb/lbp.rb +37 -0
- data/lib/acirb/leqpt.rb +117 -0
- data/lib/acirb/lldp.rb +469 -0
- data/lib/acirb/lldptlv.rb +133 -0
- data/lib/acirb/lldptlvpol.rb +133 -0
- data/lib/acirb/maint.rb +549 -0
- data/lib/acirb/mcast.rb +53 -0
- data/lib/acirb/mcp.rb +245 -0
- data/lib/acirb/memory.rb +293 -0
- data/lib/acirb/mgmt.rb +805 -0
- data/lib/acirb/mldsnoop.rb +261 -0
- data/lib/acirb/mo.rb +53 -0
- data/lib/acirb/mock.rb +69 -0
- data/lib/acirb/mon.rb +645 -0
- data/lib/acirb/monitor.rb +149 -0
- data/lib/acirb/naming.rb +37 -0
- data/lib/acirb/nd.rb +405 -0
- data/lib/acirb/nw.rb +629 -0
- data/lib/acirb/nws.rb +117 -0
- data/lib/acirb/oam.rb +53 -0
- data/lib/acirb/observer.rb +69 -0
- data/lib/acirb/opflex.rb +2693 -0
- data/lib/acirb/os.rb +37 -0
- data/lib/acirb/ospf.rb +1317 -0
- data/lib/acirb/ospfv3.rb +501 -0
- data/lib/acirb/pc.rb +181 -0
- data/lib/acirb/pcons.rb +677 -0
- data/lib/acirb/phys.rb +37 -0
- data/lib/acirb/ping.rb +101 -0
- data/lib/acirb/pki.rb +245 -0
- data/lib/acirb/pol.rb +1413 -0
- data/lib/acirb/policer.rb +37 -0
- data/lib/acirb/pool.rb +101 -0
- data/lib/acirb/pres.rb +309 -0
- data/lib/acirb/proc.rb +2085 -0
- data/lib/acirb/psu.rb +69 -0
- data/lib/acirb/qos.rb +453 -0
- data/lib/acirb/qosm.rb +645 -0
- data/lib/acirb/qosp.rb +181 -0
- data/lib/acirb/rbqm.rb +149 -0
- data/lib/acirb/regress.rb +21 -0
- data/lib/acirb/reln.rb +421 -0
- data/lib/acirb/repl.rb +69 -0
- data/lib/acirb/res.rb +197 -0
- data/lib/acirb/rib.rb +149 -0
- data/lib/acirb/rmon.rb +165 -0
- data/lib/acirb/rpm.rb +21 -0
- data/lib/acirb/rtcom.rb +53 -0
- data/lib/acirb/rtctrl.rb +949 -0
- data/lib/acirb/rtextcom.rb +69 -0
- data/lib/acirb/rtflt.rb +53 -0
- data/lib/acirb/rtleak.rb +101 -0
- data/lib/acirb/rtmap.rb +517 -0
- data/lib/acirb/rtpfx.rb +85 -0
- data/lib/acirb/rtregcom.rb +69 -0
- data/lib/acirb/rtsum.rb +21 -0
- data/lib/acirb/rule.rb +69 -0
- data/lib/acirb/satm.rb +101 -0
- data/lib/acirb/snmp.rb +549 -0
- data/lib/acirb/span.rb +1349 -0
- data/lib/acirb/stats.rb +501 -0
- data/lib/acirb/statstore.rb +69 -0
- data/lib/acirb/stormctrl.rb +53 -0
- data/lib/acirb/stp.rb +453 -0
- data/lib/acirb/sts.rb +725 -0
- data/lib/acirb/svccore.rb +133 -0
- data/lib/acirb/svi.rb +53 -0
- data/lib/acirb/synthetic.rb +709 -0
- data/lib/acirb/sysdebug.rb +293 -0
- data/lib/acirb/sysfile.rb +69 -0
- data/lib/acirb/syshist.rb +69 -0
- data/lib/acirb/syslog.rb +229 -0
- data/lib/acirb/sysmgr.rb +69 -0
- data/lib/acirb/sysmgrp.rb +37 -0
- data/lib/acirb/tag.rb +197 -0
- data/lib/acirb/task.rb +53 -0
- data/lib/acirb/test.rb +53 -0
- data/lib/acirb/testinfralab.rb +133 -0
- data/lib/acirb/tlv.rb +165 -0
- data/lib/acirb/top.rb +261 -0
- data/lib/acirb/topoctrl.rb +149 -0
- data/lib/acirb/traceroute.rb +181 -0
- data/lib/acirb/traceroutep.rb +197 -0
- data/lib/acirb/trig.rb +485 -0
- data/lib/acirb/troubleshoot.rb +133 -0
- data/lib/acirb/tunnel.rb +181 -0
- data/lib/acirb/uribv4.rb +133 -0
- data/lib/acirb/uribv6.rb +101 -0
- data/lib/acirb/vlan.rb +85 -0
- data/lib/acirb/vlanmgr.rb +37 -0
- data/lib/acirb/vmm.rb +805 -0
- data/lib/acirb/vns.rb +6853 -0
- data/lib/acirb/vpc.rb +229 -0
- data/lib/acirb/vsvc.rb +69 -0
- data/lib/acirb/vtap.rb +37 -0
- data/lib/acirb/vxlan.rb +69 -0
- data/lib/acirb/vz.rb +2325 -0
- data/lib/acirb.rb +12 -0
- data/lib/autoloadmap.rb +6372 -0
- data/lib/events.rb +27 -0
- data/lib/loader.rb +85 -0
- data/lib/logging.rb +22 -0
- data/lib/lookup.rb +6377 -0
- data/lib/mo.rb +203 -0
- data/lib/naming.rb +124 -0
- data/lib/query.rb +69 -0
- data/lib/restclient.rb +198 -0
- data/lib/version.rb +3 -0
- metadata +301 -0
data/lib/mo.rb
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
require 'restclient'
|
|
2
|
+
require 'rexml/document'
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
# rubocop:disable ClassLength
|
|
6
|
+
module ACIrb
|
|
7
|
+
# A generic managed object class
|
|
8
|
+
class MO
|
|
9
|
+
# Class variable properties
|
|
10
|
+
class << self
|
|
11
|
+
# for class variables
|
|
12
|
+
attr_reader :prefix, :class_name, :child_classes, :props,
|
|
13
|
+
:naming_props, :prefixes, :ruby_class, :containers
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# for instance variables
|
|
17
|
+
attr_reader :children, :attributes
|
|
18
|
+
attr_accessor :parent
|
|
19
|
+
|
|
20
|
+
def prefixes
|
|
21
|
+
self.class.prefixes
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def child_classes
|
|
25
|
+
self.class.child_classes
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def containers
|
|
29
|
+
self.class.containers
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def naming_props
|
|
33
|
+
self.class.naming_props
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def props
|
|
37
|
+
self.class.props
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def class_name
|
|
41
|
+
self.class.class_name
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def ruby_class
|
|
45
|
+
self.class.ruby_class
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def initialize(create_parent, create_attr = {})
|
|
49
|
+
@attributes = {}
|
|
50
|
+
props.each do |prop|
|
|
51
|
+
@attributes[prop.to_s] = ''
|
|
52
|
+
end
|
|
53
|
+
@children = []
|
|
54
|
+
|
|
55
|
+
if create_parent.nil?
|
|
56
|
+
@parent = nil
|
|
57
|
+
else
|
|
58
|
+
@parent = create_parent
|
|
59
|
+
@parent.add_child(self)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# for performance reasons, do not use set_prop here
|
|
63
|
+
# and build the dn string after all attributes are set
|
|
64
|
+
create_attr.each do |k, v|
|
|
65
|
+
@attributes[k.to_s] = v
|
|
66
|
+
end
|
|
67
|
+
@attributes['dn'] = build_dn
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def add_child(child)
|
|
71
|
+
unless child.containers.include?(ruby_class)
|
|
72
|
+
fail child.class.to_s + ' cannot be child of ' + self.class.to_s
|
|
73
|
+
end
|
|
74
|
+
@children.each do |mo|
|
|
75
|
+
return nil if mo.dn == child.dn
|
|
76
|
+
end
|
|
77
|
+
@children.push(child)
|
|
78
|
+
child.parent = self
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def set_prop(key, val)
|
|
82
|
+
key = key.to_s
|
|
83
|
+
val = val.to_s
|
|
84
|
+
return if key == 'dn' || key == 'rn'
|
|
85
|
+
@attributes[key] = val
|
|
86
|
+
if naming_props.include? key
|
|
87
|
+
dn_str = build_dn
|
|
88
|
+
@attributes['dn'] = dn_str
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def root
|
|
93
|
+
p = self
|
|
94
|
+
p = p.parent until p.parent.nil?
|
|
95
|
+
p
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def to_xml
|
|
99
|
+
# TODO: Use nokogiri here
|
|
100
|
+
# https://github.com/sparklemotion/nokogiri/wiki/Cheat-sheet
|
|
101
|
+
x = REXML::Element.new mo_type.to_s
|
|
102
|
+
@attributes.each do |key, value|
|
|
103
|
+
x.attributes[key.to_s] = value if value.to_s != ''
|
|
104
|
+
end
|
|
105
|
+
@children.each do |child|
|
|
106
|
+
x.add_element(child.to_xml)
|
|
107
|
+
end
|
|
108
|
+
x
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def to_hash
|
|
112
|
+
h = {}
|
|
113
|
+
h[mo_type.to_s] = {}
|
|
114
|
+
h[mo_type.to_s]['attributes'] = @attributes
|
|
115
|
+
h[mo_type.to_s]['attributes']['dn'] = dn
|
|
116
|
+
h[mo_type.to_s]['children'] = [] if children.length > 0
|
|
117
|
+
@children.each do |child|
|
|
118
|
+
h[mo_type.to_s]['children'].push(child.to_hash)
|
|
119
|
+
end
|
|
120
|
+
h
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def to_json
|
|
124
|
+
JSON.dump(to_hash)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def create(restclient)
|
|
128
|
+
@attributes['status'] = 'created,modified'
|
|
129
|
+
restclient.post(data: self,
|
|
130
|
+
url: "/api/mo/#{dn}.#{restclient.format}")
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def destroy(restclient)
|
|
134
|
+
@attributes['status'] = 'deleted'
|
|
135
|
+
restclient.post(data: self,
|
|
136
|
+
url: "/api/mo/#{dn}.#{restclient.format}")
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def exists(restclient, recurse = false)
|
|
140
|
+
options = {}
|
|
141
|
+
options[:subtree] = 'full' if recurse
|
|
142
|
+
if restclient.lookupByDn(dn, options)
|
|
143
|
+
if recurse == true
|
|
144
|
+
children.each do |child|
|
|
145
|
+
unless child.exists(restclient, recurse = true)
|
|
146
|
+
return false
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
return true
|
|
151
|
+
else
|
|
152
|
+
return false
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def build_dn
|
|
157
|
+
if @parent.nil?
|
|
158
|
+
return rn
|
|
159
|
+
else
|
|
160
|
+
parent_dn = '' << @parent.dn
|
|
161
|
+
if parent_dn == ''
|
|
162
|
+
return rn
|
|
163
|
+
else
|
|
164
|
+
parent_dn << '/'
|
|
165
|
+
parent_dn << rn
|
|
166
|
+
return parent_dn
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def mo_type
|
|
172
|
+
self.class.class_name.delete('.')
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def to_s
|
|
176
|
+
def hash_to_table(h)
|
|
177
|
+
len = h.keys.map(&:length).max
|
|
178
|
+
ret = []
|
|
179
|
+
h.each do |k, v|
|
|
180
|
+
ret.push(('%' + len.to_s + 's: %s') % [k.to_s, v.to_s])
|
|
181
|
+
end
|
|
182
|
+
ret
|
|
183
|
+
end
|
|
184
|
+
header_table = hash_to_table(
|
|
185
|
+
'Class' => class_name,
|
|
186
|
+
)
|
|
187
|
+
attribute_table = hash_to_table(attributes)
|
|
188
|
+
header_table.push(attribute_table)
|
|
189
|
+
header_table.join("\n")
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def method_missing(name, *args, &block)
|
|
193
|
+
lookup_name = name.to_s
|
|
194
|
+
return @attributes[lookup_name] if @attributes.include? lookup_name
|
|
195
|
+
child_matches = []
|
|
196
|
+
@children.each do |child|
|
|
197
|
+
child_matches.push(child) if child.class.prefix.sub('-', '') == lookup_name
|
|
198
|
+
end
|
|
199
|
+
return child_matches if child_matches.length > 0
|
|
200
|
+
super
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
data/lib/naming.rb
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
module ACIrb
|
|
2
|
+
class Naming
|
|
3
|
+
def self.split_outside_brackets(dn_str, splitChar)
|
|
4
|
+
depth = 0
|
|
5
|
+
place = 0
|
|
6
|
+
last_split = 0
|
|
7
|
+
pieces = []
|
|
8
|
+
while place < dn_str.length
|
|
9
|
+
c = dn_str[place]
|
|
10
|
+
if c == '['
|
|
11
|
+
depth += 1
|
|
12
|
+
elsif c == ']'
|
|
13
|
+
depth -= 1
|
|
14
|
+
end
|
|
15
|
+
if depth == 0 && c == splitChar && place != 0
|
|
16
|
+
pieces.push(dn_str[last_split..place])
|
|
17
|
+
last_split = place + 1
|
|
18
|
+
end
|
|
19
|
+
place += 1
|
|
20
|
+
end
|
|
21
|
+
pieces.push(dn_str[last_split..place - 1]) if place != last_split
|
|
22
|
+
|
|
23
|
+
pieces
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.strip_last_delimiter(str, delim)
|
|
27
|
+
if str[-1] == delim
|
|
28
|
+
return str[0..-2]
|
|
29
|
+
else
|
|
30
|
+
return str
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.strip_outer_brackets(str)
|
|
35
|
+
if str[0] == '[' && str[-1] == ']'
|
|
36
|
+
return str[1..-2]
|
|
37
|
+
else
|
|
38
|
+
return str
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.split_dn_str(dn_str)
|
|
43
|
+
rns = []
|
|
44
|
+
split_outside_brackets(dn_str, '/').each do |rn|
|
|
45
|
+
rns.push(strip_last_delimiter(rn, '/'))
|
|
46
|
+
end
|
|
47
|
+
rns
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.split_rn_str(rn_str, delims)
|
|
51
|
+
rn_pieces = []
|
|
52
|
+
delims.each_with_index do |(delim, _has_prop), index|
|
|
53
|
+
begin_delim = rn_str.split(delim)
|
|
54
|
+
|
|
55
|
+
if index == delims.length - 1
|
|
56
|
+
name_prop = begin_delim[1]
|
|
57
|
+
else
|
|
58
|
+
rn_str = begin_delim[1]
|
|
59
|
+
end_delim = rn_str.split(delims[index + 1][0])
|
|
60
|
+
name_prop = end_delim[0]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
rn_pieces.push(delim)
|
|
64
|
+
rn_pieces.push(name_prop)
|
|
65
|
+
end
|
|
66
|
+
rn_pieces
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.get_mo_from_dn(dn_str)
|
|
70
|
+
rns = split_dn_str(dn_str)
|
|
71
|
+
mo = ACIrb::TopRoot.new(nil)
|
|
72
|
+
rns.each do |rn|
|
|
73
|
+
mo = get_mo_from_rn(mo, rn)
|
|
74
|
+
end
|
|
75
|
+
mo
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def self.get_mo_from_rn(parent_mo, rn_str)
|
|
79
|
+
mo = get_class_from_child_prefix(parent_mo, rn_str).new(parent_mo)
|
|
80
|
+
return mo if mo.naming_props.length == 0
|
|
81
|
+
rn_pieces = split_rn_str(rn_str, mo.prefixes)
|
|
82
|
+
rn_values = rn_pieces.values_at(*(1..rn_pieces.length - 1).step(2))
|
|
83
|
+
mo.naming_props.each_with_index do |prop_name, index|
|
|
84
|
+
prop_val = rn_values[index]
|
|
85
|
+
mo.set_prop(prop_name.to_s, strip_outer_brackets(prop_val))
|
|
86
|
+
end
|
|
87
|
+
mo
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def self.match_prefix_in_list(rn_str, prefix_list)
|
|
91
|
+
matches = false
|
|
92
|
+
prefix_match = ''
|
|
93
|
+
prefix_list.each do |prefix|
|
|
94
|
+
if rn_str.start_with?(prefix)
|
|
95
|
+
matches = true
|
|
96
|
+
prefix_match = prefix
|
|
97
|
+
break
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
return prefix_match if matches
|
|
102
|
+
|
|
103
|
+
return nil
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def self.get_class_from_child_prefix(parent_mo, rn_str)
|
|
107
|
+
prefix_to_class = {}
|
|
108
|
+
parent_mo.child_classes.each do |c|
|
|
109
|
+
cls = ACIrb.const_get(c)
|
|
110
|
+
prefix_to_class[cls.prefix] = cls
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
lpm = prefix_to_class.keys.sort_by { |x| -1 * x.length }
|
|
114
|
+
prefix_match = match_prefix_in_list(rn_str, lpm)
|
|
115
|
+
|
|
116
|
+
if prefix_match
|
|
117
|
+
return prefix_to_class[prefix_match]
|
|
118
|
+
else
|
|
119
|
+
fail 'Unknown child prefix ' + rn_str + ' in container class ' +
|
|
120
|
+
parent_mo.class.to_s
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
data/lib/query.rb
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'restclient'
|
|
2
|
+
|
|
3
|
+
# rubocop:disable ClassLength
|
|
4
|
+
# rubocop:disable FormatString
|
|
5
|
+
module ACIrb
|
|
6
|
+
# Generic Query Interface
|
|
7
|
+
class Query
|
|
8
|
+
attr_accessor :subtree, :class_filter, :query_target, :subtree_class_filter,
|
|
9
|
+
:prop_filter, :subtree_prop_filter, :subtree_include,
|
|
10
|
+
:page_size, :include_prop, :subscribe, :sort_order
|
|
11
|
+
|
|
12
|
+
def make_options
|
|
13
|
+
query_params = []
|
|
14
|
+
|
|
15
|
+
query_params.push('rsp-subtree=%s' % @subtree) \
|
|
16
|
+
if @subtree
|
|
17
|
+
query_params.push('target-subtree-class=%s' % @class_filter) \
|
|
18
|
+
if @class_filter
|
|
19
|
+
query_params.push('query-target=%s' % @query_target) \
|
|
20
|
+
if @query_target
|
|
21
|
+
query_params.push('rsp-subtree-class=%s' % @subtree_class_filter) \
|
|
22
|
+
if @subtree_class_filter
|
|
23
|
+
query_params.push('query-target-filter=%s' % @prop_filter) \
|
|
24
|
+
if @prop_filter
|
|
25
|
+
query_params.push('rsp-subtree-filter=%s' % @subtree_prop_filter) \
|
|
26
|
+
if @subtree_prop_filter
|
|
27
|
+
query_params.push('rsp-subtree-include=%s' % @subtree_include) \
|
|
28
|
+
if @subtree_include
|
|
29
|
+
query_params.push('page-size=%s' % @page_size) \
|
|
30
|
+
if @page_size
|
|
31
|
+
query_params.push('order-by=%s' % @sort_order) \
|
|
32
|
+
if @sort_order
|
|
33
|
+
query_params.push('rsp-prop-include=%s' % @include_prop) \
|
|
34
|
+
if @include_prop
|
|
35
|
+
query_params.push('subscription=yes') \
|
|
36
|
+
if @subscribe
|
|
37
|
+
|
|
38
|
+
if query_params.length > 0
|
|
39
|
+
'?' + query_params.join('&')
|
|
40
|
+
else
|
|
41
|
+
''
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Dn Query
|
|
47
|
+
class DnQuery < Query
|
|
48
|
+
attr_accessor :dn
|
|
49
|
+
def initialize(dn)
|
|
50
|
+
@dn = dn
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def uri(format)
|
|
54
|
+
'/api/mo/%s.%s%s' % [@dn, format, make_options]
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Class Query
|
|
59
|
+
class ClassQuery < Query
|
|
60
|
+
attr_accessor :cls
|
|
61
|
+
def initialize(cls)
|
|
62
|
+
@cls = cls
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def uri(format)
|
|
66
|
+
'/api/class/%s.%s%s' % [@cls, format, make_options]
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
data/lib/restclient.rb
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
require 'httpclient'
|
|
2
|
+
require 'openssl'
|
|
3
|
+
require 'nokogiri'
|
|
4
|
+
require 'json'
|
|
5
|
+
# require 'uri'
|
|
6
|
+
|
|
7
|
+
# rubocop:disable ClassLength
|
|
8
|
+
module ACIrb
|
|
9
|
+
# REST client end point implementation
|
|
10
|
+
|
|
11
|
+
class RestClient
|
|
12
|
+
attr_accessor :format, :user, :password, :baseurl, :debug, :refresh_time
|
|
13
|
+
attr_reader :auth_cookie
|
|
14
|
+
# Desc: initialize a rest client
|
|
15
|
+
# Returns: does not return anything, but will raise an exception
|
|
16
|
+
# if authentication fails
|
|
17
|
+
# Parameters: accepts a hash of options:
|
|
18
|
+
# url : string. URL of APIC
|
|
19
|
+
# user : string. User ID for authentication
|
|
20
|
+
# password : string. Password for authentication
|
|
21
|
+
# debug : true or false. Flag for enabling verbose REST output
|
|
22
|
+
# format : 'xml' or 'json'. Defaults to xml
|
|
23
|
+
# verify : true or false. verify the SSL certificate. Defaults to disabled
|
|
24
|
+
def initialize(options = {})
|
|
25
|
+
uri = URI.parse(options[:url])
|
|
26
|
+
@baseurl = '%s://%s' % [uri.scheme, uri.host]
|
|
27
|
+
@format = options[:format] ? options[:format] : 'xml'
|
|
28
|
+
|
|
29
|
+
@user = options[:user]
|
|
30
|
+
@password = options[:password]
|
|
31
|
+
|
|
32
|
+
@client = HTTPClient.new
|
|
33
|
+
|
|
34
|
+
@client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE \
|
|
35
|
+
unless options[:verify] && uri.scheme == 'https'
|
|
36
|
+
|
|
37
|
+
@debug = options[:debug]
|
|
38
|
+
|
|
39
|
+
@auth_cookie = ''
|
|
40
|
+
|
|
41
|
+
authenticate if @user && @password
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Desc: authenticates the REST session with the APIC and receives an
|
|
45
|
+
# auth_cookie/token
|
|
46
|
+
# Returns: does not return anything, but will raise an exception if
|
|
47
|
+
# authentication fails
|
|
48
|
+
# Parameters: does not accept any parameters
|
|
49
|
+
def authenticate
|
|
50
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
|
51
|
+
xml.aaaUser(name: @user, pwd: @password)
|
|
52
|
+
end
|
|
53
|
+
post_url = URI.encode(@baseurl.to_s + '/api/mo/aaaLogin.xml')
|
|
54
|
+
puts 'POST REQUEST', post_url if @debug
|
|
55
|
+
puts 'POST BODY', builder.to_xml if @debug
|
|
56
|
+
response = @client.post(post_url, body: builder.to_xml)
|
|
57
|
+
puts 'POST RESPONSE: ', response.body if @debug
|
|
58
|
+
doc = Nokogiri::XML(response.body)
|
|
59
|
+
fail 'Authentication error(%s): %s' % [doc.at_css('error')['code'], doc.at_css('error')['text']] \
|
|
60
|
+
if doc.at_css('error')
|
|
61
|
+
@auth_cookie = doc.at_css('aaaLogin')['token']
|
|
62
|
+
@refresh_time = doc.at_css('aaaLogin')['refreshTimeoutSeconds']
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def refresh_session
|
|
66
|
+
get_url = URI.encode(@baseurl.to_s + '/api/mo/aaaRefresh.xml')
|
|
67
|
+
puts 'GET REQUEST', get_url if @debug
|
|
68
|
+
response = @client.get(get_url)
|
|
69
|
+
puts 'GET RESPONSE: ', response.body if @debug
|
|
70
|
+
doc = Nokogiri::XML(response.body)
|
|
71
|
+
fail 'Authentication error(%s): %s' % [doc.at_css('error')['code'], doc.at_css('error')['text']] \
|
|
72
|
+
if doc.at_css('error')
|
|
73
|
+
@auth_cookie = doc.at_css('aaaLogin')['token']
|
|
74
|
+
@refresh_time = doc.at_css('aaaLogin')['refreshTimeoutSeconds']
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Desc: Perform a Net::HTTP::Post to the REST interface with the
|
|
78
|
+
# parameters provided
|
|
79
|
+
# Returns: an array of managed object containing the parsed result
|
|
80
|
+
# Parameters: a single hash array is accepted, with the following keys:
|
|
81
|
+
# data : This is a string containing the data to be posted. This
|
|
82
|
+
# should be well formed XML that the APIC REST interface can interpret.
|
|
83
|
+
# No validation is done
|
|
84
|
+
# url : this is the path to the REST interface method being
|
|
85
|
+
# utilized, typicalliy /api/mo/.xml
|
|
86
|
+
|
|
87
|
+
def post(options)
|
|
88
|
+
post_url = URI.encode(@baseurl.to_s + options[:url].to_s)
|
|
89
|
+
|
|
90
|
+
data = options[:data]
|
|
91
|
+
if @format == 'xml'
|
|
92
|
+
data = data.to_xml
|
|
93
|
+
elsif @format == 'json'
|
|
94
|
+
data = data.to_json
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
puts 'POST REQUEST', post_url if @debug
|
|
98
|
+
puts 'POST BODY', data if @debug
|
|
99
|
+
response = @client.post(post_url, body: data)
|
|
100
|
+
puts 'POST RESPONSE: ', response.body if @debug
|
|
101
|
+
|
|
102
|
+
parse_response(response)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Desc: Perform a Net::HTTP::Get to the REST interface with the
|
|
106
|
+
# parameters provided
|
|
107
|
+
# Returns: an array of managed object containing the parsed result
|
|
108
|
+
# Parameters: a single hash array is accepted, with the following keys:
|
|
109
|
+
# url : this is the path to the REST interface method being utilized,
|
|
110
|
+
# typicalliy /api/mo/.xml with some parameters
|
|
111
|
+
|
|
112
|
+
def get(options)
|
|
113
|
+
get_url = URI.encode(@baseurl.to_s + options[:url].to_s)
|
|
114
|
+
|
|
115
|
+
puts 'GET REQUEST', get_url if @debug
|
|
116
|
+
response = @client.get(get_url)
|
|
117
|
+
puts 'GET RESPONSE: ', response.body if @debug
|
|
118
|
+
|
|
119
|
+
parse_response(response)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def parse_error(doc)
|
|
123
|
+
if format == 'xml'
|
|
124
|
+
fail 'Error response from APIC (%s): "%s"' % \
|
|
125
|
+
[doc.at_css('error')['code'], doc.at_css('error')['text']] \
|
|
126
|
+
if doc.at_css('error')
|
|
127
|
+
elsif format == 'json'
|
|
128
|
+
fail 'Error response from APIC (%s): "%s"' % \
|
|
129
|
+
[doc['imdata'][0]['error']['attributes']['code'].to_s, \
|
|
130
|
+
doc['imdata'][0]['error']['attributes']['text'].to_s] \
|
|
131
|
+
if doc['imdata'].length > 0 && doc['imdata'][0].include?('error')
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def parse_response(response)
|
|
136
|
+
if format == 'xml'
|
|
137
|
+
xml_data = response.body
|
|
138
|
+
doc = Nokogiri::XML(xml_data)
|
|
139
|
+
|
|
140
|
+
parse_error(doc)
|
|
141
|
+
|
|
142
|
+
mos = []
|
|
143
|
+
doc.root.elements.each do |xml_obj|
|
|
144
|
+
mo = ACIrb::Loader.load_xml(xml_obj)
|
|
145
|
+
mos.push(mo)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
return mos
|
|
149
|
+
|
|
150
|
+
elsif format == 'json'
|
|
151
|
+
json_data = response.body
|
|
152
|
+
doc = JSON.parse(json_data)
|
|
153
|
+
|
|
154
|
+
parse_error(doc)
|
|
155
|
+
|
|
156
|
+
mos = []
|
|
157
|
+
doc['imdata'].each do |json_obj|
|
|
158
|
+
mo = ACIrb::Loader.load_json(json_obj)
|
|
159
|
+
mos.push(mo)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
return mos
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def query(query)
|
|
167
|
+
query_uri = query.uri(@format)
|
|
168
|
+
get(url: query_uri)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Desc: A helper function that will lookup a given DN via the
|
|
172
|
+
# APIC REST interface
|
|
173
|
+
# Returns: Returns Mo for match if one exists, otherwise nil
|
|
174
|
+
# Parameters:
|
|
175
|
+
# dn : string. the distinguished name to query
|
|
176
|
+
# options : hash. set query parameters
|
|
177
|
+
|
|
178
|
+
def lookupByDn(dn, options = {})
|
|
179
|
+
subtree = options[:subtree]
|
|
180
|
+
dn_query = ACIrb::DnQuery.new(dn)
|
|
181
|
+
dn_query.subtree = subtree
|
|
182
|
+
|
|
183
|
+
mos = query(dn_query)
|
|
184
|
+
if mos.length == 1
|
|
185
|
+
return mos[0]
|
|
186
|
+
else
|
|
187
|
+
return nil
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def lookupByClass(cls, options = {})
|
|
192
|
+
subtree = options[:subtree]
|
|
193
|
+
cls_query = ACIrb::ClassQuery.new(cls)
|
|
194
|
+
cls_query.subtree = subtree
|
|
195
|
+
query(cls_query)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
data/lib/version.rb
ADDED