acirb 1.0.4h

Sign up to get free protection for your applications and to get access to all the features.
Files changed (198) hide show
  1. checksums.yaml +7 -0
  2. data/lib/acirb/aaa.rb +1477 -0
  3. data/lib/acirb/ac.rb +133 -0
  4. data/lib/acirb/action.rb +533 -0
  5. data/lib/acirb/actrl.rb +1269 -0
  6. data/lib/acirb/actrlcap.rb +37 -0
  7. data/lib/acirb/adcom.rb +421 -0
  8. data/lib/acirb/aib.rb +85 -0
  9. data/lib/acirb/arp.rb +309 -0
  10. data/lib/acirb/bfd.rb +245 -0
  11. data/lib/acirb/bgp.rb +1109 -0
  12. data/lib/acirb/callhome.rb +373 -0
  13. data/lib/acirb/cap.rb +101 -0
  14. data/lib/acirb/cdp.rb +325 -0
  15. data/lib/acirb/cnw.rb +101 -0
  16. data/lib/acirb/comm.rb +2981 -0
  17. data/lib/acirb/comp.rb +3285 -0
  18. data/lib/acirb/compat.rb +613 -0
  19. data/lib/acirb/condition.rb +213 -0
  20. data/lib/acirb/config.rb +261 -0
  21. data/lib/acirb/coop.rb +709 -0
  22. data/lib/acirb/copp.rb +645 -0
  23. data/lib/acirb/ctrlr.rb +37 -0
  24. data/lib/acirb/ctx.rb +101 -0
  25. data/lib/acirb/datetime.rb +389 -0
  26. data/lib/acirb/dbg.rb +1397 -0
  27. data/lib/acirb/dbgac.rb +757 -0
  28. data/lib/acirb/dbgexp.rb +661 -0
  29. data/lib/acirb/dhcp.rb +1141 -0
  30. data/lib/acirb/dhcptlv.rb +133 -0
  31. data/lib/acirb/dhcptlvpol.rb +133 -0
  32. data/lib/acirb/dlgt.rb +21 -0
  33. data/lib/acirb/dns.rb +293 -0
  34. data/lib/acirb/draw.rb +37 -0
  35. data/lib/acirb/edr.rb +85 -0
  36. data/lib/acirb/eigrp.rb +789 -0
  37. data/lib/acirb/ep.rb +69 -0
  38. data/lib/acirb/epm.rb +133 -0
  39. data/lib/acirb/eptrk.rb +117 -0
  40. data/lib/acirb/eqpt.rb +6405 -0
  41. data/lib/acirb/eqptcap.rb +197 -0
  42. data/lib/acirb/eqptcapacity.rb +4069 -0
  43. data/lib/acirb/eqptdiag.rb +181 -0
  44. data/lib/acirb/eqptdiagp.rb +981 -0
  45. data/lib/acirb/ethpm.rb +309 -0
  46. data/lib/acirb/event.rb +197 -0
  47. data/lib/acirb/extnw.rb +181 -0
  48. data/lib/acirb/fabric.rb +6693 -0
  49. data/lib/acirb/fault.rb +821 -0
  50. data/lib/acirb/file.rb +149 -0
  51. data/lib/acirb/firmware.rb +645 -0
  52. data/lib/acirb/fmcast.rb +101 -0
  53. data/lib/acirb/frmwrk.rb +277 -0
  54. data/lib/acirb/fsm.rb +21 -0
  55. data/lib/acirb/fv.rb +6901 -0
  56. data/lib/acirb/fvcap.rb +37 -0
  57. data/lib/acirb/fvns.rb +533 -0
  58. data/lib/acirb/fvtopo.rb +85 -0
  59. data/lib/acirb/geo.rb +133 -0
  60. data/lib/acirb/glean.rb +85 -0
  61. data/lib/acirb/ha.rb +21 -0
  62. data/lib/acirb/health.rb +341 -0
  63. data/lib/acirb/hvs.rb +357 -0
  64. data/lib/acirb/icmp.rb +69 -0
  65. data/lib/acirb/icmpv4.rb +69 -0
  66. data/lib/acirb/icmpv6.rb +85 -0
  67. data/lib/acirb/ident.rb +693 -0
  68. data/lib/acirb/igmp.rb +69 -0
  69. data/lib/acirb/igmpsnoop.rb +293 -0
  70. data/lib/acirb/im.rb +117 -0
  71. data/lib/acirb/imginstall.rb +21 -0
  72. data/lib/acirb/infra.rb +3893 -0
  73. data/lib/acirb/ip.rb +389 -0
  74. data/lib/acirb/ipmcsnoop.rb +293 -0
  75. data/lib/acirb/ipv4.rb +133 -0
  76. data/lib/acirb/ipv6.rb +149 -0
  77. data/lib/acirb/isis.rb +1653 -0
  78. data/lib/acirb/isistlv.rb +133 -0
  79. data/lib/acirb/l1.rb +741 -0
  80. data/lib/acirb/l1cap.rb +37 -0
  81. data/lib/acirb/l2.rb +2437 -0
  82. data/lib/acirb/l2cap.rb +37 -0
  83. data/lib/acirb/l2ext.rb +309 -0
  84. data/lib/acirb/l3.rb +613 -0
  85. data/lib/acirb/l3cap.rb +37 -0
  86. data/lib/acirb/l3ext.rb +949 -0
  87. data/lib/acirb/l3vm.rb +53 -0
  88. data/lib/acirb/l4.rb +53 -0
  89. data/lib/acirb/lacp.rb +293 -0
  90. data/lib/acirb/lbp.rb +37 -0
  91. data/lib/acirb/leqpt.rb +117 -0
  92. data/lib/acirb/lldp.rb +469 -0
  93. data/lib/acirb/lldptlv.rb +133 -0
  94. data/lib/acirb/lldptlvpol.rb +133 -0
  95. data/lib/acirb/maint.rb +549 -0
  96. data/lib/acirb/mcast.rb +53 -0
  97. data/lib/acirb/mcp.rb +245 -0
  98. data/lib/acirb/memory.rb +293 -0
  99. data/lib/acirb/mgmt.rb +805 -0
  100. data/lib/acirb/mldsnoop.rb +261 -0
  101. data/lib/acirb/mo.rb +53 -0
  102. data/lib/acirb/mock.rb +69 -0
  103. data/lib/acirb/mon.rb +645 -0
  104. data/lib/acirb/monitor.rb +149 -0
  105. data/lib/acirb/naming.rb +37 -0
  106. data/lib/acirb/nd.rb +405 -0
  107. data/lib/acirb/nw.rb +629 -0
  108. data/lib/acirb/nws.rb +117 -0
  109. data/lib/acirb/oam.rb +53 -0
  110. data/lib/acirb/observer.rb +69 -0
  111. data/lib/acirb/opflex.rb +2693 -0
  112. data/lib/acirb/os.rb +37 -0
  113. data/lib/acirb/ospf.rb +1317 -0
  114. data/lib/acirb/ospfv3.rb +501 -0
  115. data/lib/acirb/pc.rb +181 -0
  116. data/lib/acirb/pcons.rb +677 -0
  117. data/lib/acirb/phys.rb +37 -0
  118. data/lib/acirb/ping.rb +101 -0
  119. data/lib/acirb/pki.rb +245 -0
  120. data/lib/acirb/pol.rb +1413 -0
  121. data/lib/acirb/policer.rb +37 -0
  122. data/lib/acirb/pool.rb +101 -0
  123. data/lib/acirb/pres.rb +309 -0
  124. data/lib/acirb/proc.rb +2085 -0
  125. data/lib/acirb/psu.rb +69 -0
  126. data/lib/acirb/qos.rb +453 -0
  127. data/lib/acirb/qosm.rb +645 -0
  128. data/lib/acirb/qosp.rb +181 -0
  129. data/lib/acirb/rbqm.rb +149 -0
  130. data/lib/acirb/regress.rb +21 -0
  131. data/lib/acirb/reln.rb +421 -0
  132. data/lib/acirb/repl.rb +69 -0
  133. data/lib/acirb/res.rb +197 -0
  134. data/lib/acirb/rib.rb +149 -0
  135. data/lib/acirb/rmon.rb +165 -0
  136. data/lib/acirb/rpm.rb +21 -0
  137. data/lib/acirb/rtcom.rb +53 -0
  138. data/lib/acirb/rtctrl.rb +949 -0
  139. data/lib/acirb/rtextcom.rb +69 -0
  140. data/lib/acirb/rtflt.rb +53 -0
  141. data/lib/acirb/rtleak.rb +101 -0
  142. data/lib/acirb/rtmap.rb +517 -0
  143. data/lib/acirb/rtpfx.rb +85 -0
  144. data/lib/acirb/rtregcom.rb +69 -0
  145. data/lib/acirb/rtsum.rb +21 -0
  146. data/lib/acirb/rule.rb +69 -0
  147. data/lib/acirb/satm.rb +101 -0
  148. data/lib/acirb/snmp.rb +549 -0
  149. data/lib/acirb/span.rb +1349 -0
  150. data/lib/acirb/stats.rb +501 -0
  151. data/lib/acirb/statstore.rb +69 -0
  152. data/lib/acirb/stormctrl.rb +53 -0
  153. data/lib/acirb/stp.rb +453 -0
  154. data/lib/acirb/sts.rb +725 -0
  155. data/lib/acirb/svccore.rb +133 -0
  156. data/lib/acirb/svi.rb +53 -0
  157. data/lib/acirb/synthetic.rb +709 -0
  158. data/lib/acirb/sysdebug.rb +293 -0
  159. data/lib/acirb/sysfile.rb +69 -0
  160. data/lib/acirb/syshist.rb +69 -0
  161. data/lib/acirb/syslog.rb +229 -0
  162. data/lib/acirb/sysmgr.rb +69 -0
  163. data/lib/acirb/sysmgrp.rb +37 -0
  164. data/lib/acirb/tag.rb +197 -0
  165. data/lib/acirb/task.rb +53 -0
  166. data/lib/acirb/test.rb +53 -0
  167. data/lib/acirb/testinfralab.rb +133 -0
  168. data/lib/acirb/tlv.rb +165 -0
  169. data/lib/acirb/top.rb +261 -0
  170. data/lib/acirb/topoctrl.rb +149 -0
  171. data/lib/acirb/traceroute.rb +181 -0
  172. data/lib/acirb/traceroutep.rb +197 -0
  173. data/lib/acirb/trig.rb +485 -0
  174. data/lib/acirb/troubleshoot.rb +133 -0
  175. data/lib/acirb/tunnel.rb +181 -0
  176. data/lib/acirb/uribv4.rb +133 -0
  177. data/lib/acirb/uribv6.rb +101 -0
  178. data/lib/acirb/vlan.rb +85 -0
  179. data/lib/acirb/vlanmgr.rb +37 -0
  180. data/lib/acirb/vmm.rb +805 -0
  181. data/lib/acirb/vns.rb +6853 -0
  182. data/lib/acirb/vpc.rb +229 -0
  183. data/lib/acirb/vsvc.rb +69 -0
  184. data/lib/acirb/vtap.rb +37 -0
  185. data/lib/acirb/vxlan.rb +69 -0
  186. data/lib/acirb/vz.rb +2325 -0
  187. data/lib/acirb.rb +12 -0
  188. data/lib/autoloadmap.rb +6372 -0
  189. data/lib/events.rb +27 -0
  190. data/lib/loader.rb +85 -0
  191. data/lib/logging.rb +22 -0
  192. data/lib/lookup.rb +6377 -0
  193. data/lib/mo.rb +203 -0
  194. data/lib/naming.rb +124 -0
  195. data/lib/query.rb +69 -0
  196. data/lib/restclient.rb +198 -0
  197. data/lib/version.rb +3 -0
  198. 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
@@ -0,0 +1,3 @@
1
+ module ACIrb
2
+ VERSION = '1.0.4h'
3
+ end