1
2
3
4
5
6
7
8
9
10 """
11 Operations for MIBs.
12
13 Available at: /zport/dmd/mib_router
14 """
15
16 import logging
17 import re
18 from Products.ZenUtils.Ext import DirectResponse
19 from Products.Zuul.routers import TreeRouter
20 from Products.Zuul.decorators import require
21 from Products.Zuul.interfaces import IInfo
22 from Products.Zuul.form.interfaces import IFormBuilder
23 from Products import Zuul
24 from Products.ZenMessaging.audit import audit
25
26 log = logging.getLogger('zen.MibRouter')
30 """
31 A JSON/ExtDirect interface to operations on MIBs
32 """
33
35 self.api = Zuul.getFacade('mibs')
36 self.context = context
37 self.request = request
38 super(MibRouter, self).__init__(context, request)
39
42
43 - def getTree(self, id='/zport/dmd/Mibs'):
44 """
45 Returns the tree structure of an organizer hierarchy. Default tree
46 root is MIBs.
47
48 @type id: string
49 @param id: (optional) Id of the root node of the tree to be
50 returned (default: '/zport/dmd/Mibs')
51 @rtype: [dictionary]
52 @return: Object representing the tree
53 """
54 tree = self.api.getTree(id)
55 data = Zuul.marshal(tree)
56 return [data]
57
59 """
60 Returns the tree structure of an organizer hierarchy, only including
61 organizers.
62
63 @type id: string
64 @param id: Id of the root node of the tree to be returned
65 @rtype: [dictionary]
66 @return: Object representing the organizer tree
67 """
68 tree = self.api.getOrganizerTree(id)
69 data = Zuul.marshal(tree)
70 return [data]
71
72 @require('Manage DMD')
73 - def addNode(self, contextUid='', id='', type=''):
74 """
75 Add an organizer or new blank MIB.
76
77 @type contextUid: string
78 @param contextUid: Context to attach new node
79 @type id: string
80 @param id: Id of the new orgainzer or blank MIB
81 @type type: string
82 @param type: Type of new node. Can be 'organizer' or 'MIB'
83 @rtype: DirectResponse
84 @return: B{Properties}:
85 - tree: ([dictionary]) Object representing the new tree
86 """
87
88 nodeType = type
89 try:
90 if nodeType == 'organizer':
91 uid = contextUid + '/' + id
92 maoUid = uid.replace('/zport/dmd', '')
93 self.context.dmd.Mibs.manage_addOrganizer(maoUid)
94 self.context.dmd.restrictedTraverse(uid)
95 audit('UI.Organizer.Add', uid)
96 elif nodeType == 'MIB':
97 container = self.context.dmd.restrictedTraverse(contextUid)
98 container.manage_addMibModule(id)
99 audit('UI.Mib.Add', contextUid + '/' + id)
100 else:
101 return DirectResponse.fail(
102 'Invalid node type "%s"' % nodeType
103 )
104 return DirectResponse.succeed(tree=self.getTree())
105 except Exception as ex:
106 log.exception(ex)
107 return DirectResponse.exception(
108 ex, message="Failed to create '{}'".format(id)
109 )
110
111 @require('Manage DMD')
112 - def addMIB(self, package, organizer='/'):
113 """
114 Add a new MIB by URL or local file.
115
116 @type package: string
117 @param package: URL or local file path to MIB file
118 @type organizer: string
119 @param organizer: ID of the organizer to add MIB to
120 @rtype: DirectResponse
121 @return: B{Properties}:
122 - jobId: (string) ID of the add MIB job
123 """
124 facade = self._getFacade()
125 jobrecord = facade.addMibPackage(package, organizer)
126 if not jobrecord:
127 return DirectResponse.fail(
128 "Failed to add MIB package %s" % package
129 )
130 audit('UI.Mib.AddFromPackage', mibpackage=package, organizer=organizer)
131 return DirectResponse.succeed(new_jobs=Zuul.marshal(
132 [jobrecord], keys=('uuid', 'description', 'started')
133 ))
134
135 @require('Manage DMD')
137 """
138 Remove an organizer or MIB.
139
140 @type uid: string
141 @param uid: UID of organizer or MIB to remove
142 @rtype: DirectResponse
143 @return: B{Properties}:
144 - tree: ([dictionary]) Object representing the new tree
145 """
146 represented = self.context.dmd.restrictedTraverse(uid)
147 organizer = represented.getParentNode()
148 if represented.meta_type == 'MibOrganizer':
149 organizer.manage_deleteOrganizer(represented.id)
150 audit('UI.Organizer.Delete', represented.id)
151 else:
152 organizer.removeMibModules(ids=represented.id)
153 mibUids = represented.id
154 if isinstance(mibUids, basestring):
155 mibUids = (mibUids,)
156 for mibUid in mibUids:
157 audit('UI.Mib.Remove', mibUid)
158 return DirectResponse.succeed(tree=self.getTree())
159
160 @require('Manage DMD')
162 """
163 Move an organizer or MIB from one organizer to another.
164
165 @type uids: [string]
166 @param uids: UIDs of organizers and MIBs to move
167 @type target: string
168 @param target: UID of the organizer to move to
169 @rtype: DirectResponse
170 @return: B{Properties}:
171 - data: (dictionary) Object representing the new parent organizer
172 """
173 parent = self.api.moveMibs(uids, target)
174 parent = IInfo(parent)
175 for uid in uids:
176 audit('UI.Mib.Move', uid, target=target)
177 return DirectResponse.succeed(data=Zuul.marshal(parent))
178
179 - def getInfo(self, uid, useFieldSets=True):
180 """
181 Get the properties of a MIB
182
183 @type uid: string
184 @param uid: Unique identifier of a MIB
185 @type useFieldSets: boolean
186 @param useFieldSets: True to return a fieldset version of the info form
187 (default: True)
188 @rtype: DirectResponse
189 @return: B{Properties}
190 - data: (dictionary) Object representing a MIB's properties
191 - form: (dictionary) Object representing an edit form for a MIB's
192 properties
193 """
194 info = self.api.getInfo(uid)
195 form = IFormBuilder(info).render(fieldsets=useFieldSets)
196 return DirectResponse.succeed(data=Zuul.marshal(info), form=form)
197
198 @require('Manage DMD')
200 """
201 Set attributes on a MIB.
202 This method accepts any keyword argument for the property that you wish
203 to set. The only required property is "uid".
204
205 @type uid: string
206 @keyword uid: Unique identifier of a MIB
207 @rtype: DirectResponse
208 @return: B{Properties}
209 - data: (dictionary) Object representing a MIB's new properties
210 """
211 uid = data['uid']
212 del data['uid']
213 facade = self._getFacade()
214 info = facade.setInfo(uid, data)
215 audit('UI.Mib.Edit', uid, data_=data)
216 return DirectResponse.succeed(data=Zuul.marshal(info))
217
219 """
220 Check for illegal characters in OID
221 """
222 oidRegex = re.compile('^[.0-9]+$')
223 matched = oidRegex.match(oid)
224 return bool(matched)
225
226 @require('Manage DMD')
228 if not self._validateOid(oid):
229 msg = "Invalid OID value %s" % oid
230 return DirectResponse.fail(msg)
231 self.api.addOidMapping(uid, id, oid, nodetype)
232 audit('UI.Mib.AddOidMapping', uid, id=id, oid=oid, nodetype=nodetype)
233 return DirectResponse.succeed()
234
235 @require('Manage DMD')
236 - def addTrap(self, uid, id, oid, nodetype='notification'):
237 if not self._validateOid(oid):
238 msg = "Invalid OID value %s" % oid
239 return DirectResponse.fail(msg)
240 self.api.addTrap(uid, id, oid, nodetype)
241 audit('UI.Mib.AddTrap', uid, id=id, oid=oid, nodetype=nodetype)
242 return DirectResponse.succeed()
243
244 @require('Manage DMD')
246 if uid.find('/nodes/') == -1:
247 return DirectResponse.fail(
248 '"%s" does not appear to refer to an OID Mapping' % uid
249 )
250 mibUid, mappingId = uid.split('/nodes/')
251 self.api.deleteOidMapping(mibUid, mappingId)
252 audit('UI.Mib.DeleteOidMapping', mibUid, mapping=mappingId)
253 return DirectResponse.succeed()
254
255 @require('Manage DMD')
257 if uid.find('/notifications/') == -1:
258 return DirectResponse.fail(
259 '"%s" does not appear to refer to a trap' % uid
260 )
261 mibUid, trapId = uid.split('/notifications/')
262 self.api.deleteTrap(mibUid, trapId)
263 audit('UI.Mib.DeleteTrap', mibUid, trap=trapId)
264 return DirectResponse.succeed()
265
266 - def getOidMappings(
267 self, uid, dir='ASC', sort='name', start=0, page=None, limit=256):
268 count, nodes = self.api.getMibNodes(
269 uid=uid, dir=dir, sort=sort, start=start,
270 limit=limit, relation='nodes'
271 )
272 return DirectResponse.succeed(count=count, data=Zuul.marshal(nodes))
273
274 - def getTraps(
275 self, uid, dir='ASC', sort='name', start=0, page=None, limit=256):
276 count, nodes = self.api.getMibNodes(
277 uid=uid, dir=dir, sort=sort, start=start,
278 limit=limit, relation='notifications'
279 )
280 return DirectResponse.succeed(count=count, data=Zuul.marshal(nodes))
281
283 try:
284 node = next(iter(self.api.getOidList(oid)), None)
285 except Exception as ex:
286 log.warn("Error while looking up OID '%s': %s", oid, ex)
287 node = None
288 if node is None:
289 return DirectResponse.fail()
290 return DirectResponse.succeed(info=Zuul.marshal(IInfo(node)))
291
293 """
294 A MIB node is a regular OID (ie you can hit it with snmpwalk)
295 """
296 if id is None:
297 return []
298 tree = self.api.getMibNodeTree(id)
299 if tree is None:
300 return []
301 data = Zuul.marshal(tree)
302 return [data]
303
305 """
306 A MIB trap node is an OID received from a trap
307 """
308 if id is None:
309 return []
310 tree = self.api.getMibTrapTree(id)
311 if tree is None:
312 return []
313 data = Zuul.marshal(tree)
314 return [data]
315