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.
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