Package Products ::
Package Zuul ::
Package routers
|
|
1
2
3
4
5
6
7
8
9
10
11 """
12 Zenoss JSON API
13 """
14
15 from Products.ZenUtils.Ext import DirectRouter, DirectResponse
16 from Products.Zuul.decorators import contextRequire
17 from Products.Zuul.interfaces.tree import ICatalogTool
18 from Products.Zuul.marshalling import Marshaller
19 from Products.ZenModel.DeviceClass import DeviceClass
20 from Products.ZenModel.System import System
21 from Products.ZenMessaging.audit import audit
22 from Products.ZenUtils.Utils import getDisplayType
23 from Products import Zuul
24 import logging
25 import zlib
26 import base64
27 log = logging.getLogger(__name__)
31 """
32 A common base class for routers that have a hierarchical tree structure.
33 """
34
35 @contextRequire("Manage DMD", 'contextUid')
36 - def addNode(self, type, contextUid, id, description=None):
37 """
38 Add a node to the existing tree underneath the node specified
39 by the context UID
40
41 @type type: string
42 @param type: Either 'class' or 'organizer'
43 @type contextUid: string
44 @param contextUid: Path to the node that will
45 be the new node's parent (ex. /zport/dmd/Devices)
46 @type id: string
47 @param id: Identifier of the new node, must be unique in the
48 parent context
49 @type description: string
50 @param description: (optional) Describes this new node (default: None)
51 @rtype: dictionary
52 @return: Marshaled form of the created node
53 """
54 result = {}
55 try:
56 facade = self._getFacade()
57 if type.lower() == 'class':
58 uid = facade.addClass(contextUid, id)
59 audit('UI.Class.Add', uid)
60 else:
61 organizer = facade.addOrganizer(contextUid, id, description)
62 uid = organizer.uid
63 audit(['UI', getDisplayType(organizer), 'Add'], organizer)
64
65 treeNode = facade.getTree(uid)
66 result['nodeConfig'] = Zuul.marshal(treeNode)
67 result['success'] = True
68 except Exception, e:
69 log.exception(e)
70 result['msg'] = str(e)
71 result['success'] = False
72 return result
73
74 @contextRequire("Manage DMD", 'uid')
76 """
77 Deletes a node from the tree.
78
79 B{NOTE}: You can not delete a root node of a tree
80
81 @type uid: string
82 @param uid: Unique identifier of the node we wish to delete
83 @rtype: DirectResponse
84 @return: B{Properties}:
85 - msg: (string) Status message
86 """
87
88 if not self._canDeleteUid(uid):
89 raise Exception('You cannot delete the root node')
90 facade = self._getFacade()
91 node = facade._getObject(uid)
92
93
94
95
96 if isinstance(node, DeviceClass):
97 childBrains = ICatalogTool(node).search((
98 'Products.ZenModel.DeviceClass.DeviceClass',
99 'Products.ZenModel.Device.Device',
100 ))
101 for child in childBrains:
102 audit(['UI', getDisplayType(child), 'Delete'], child.getPath())
103 elif isinstance(node, System):
104
105 for dev in facade.getDevices(uid):
106 newSystems = facade._removeOrganizer(node, dev._object.getSystemNames())
107 dev._object.setSystems(newSystems)
108 audit(['UI', getDisplayType(node), 'Delete'], node)
109 else:
110 audit(['UI', getDisplayType(node), 'Delete'], node)
111
112 facade.deleteNode(uid)
113 msg = "Deleted node '%s'" % uid
114 return DirectResponse.succeed(msg=msg)
115
117 """
118 Move the organizer uid to be underneath the organizer
119 specified by the targetUid.
120
121 @type targetUid: string
122 @param targetUid: New parent of the organizer
123 @type organizerUid: string
124 @param organizerUid: The organizer to move
125 @rtype: DirectResponse
126 @return: B{Properties}:
127 - data: (dictionary) Moved organizer
128 """
129 facade = self._getFacade()
130 display_type = getDisplayType(facade._getObject(organizerUid))
131 audit(['UI', display_type, 'Move'], organizerUid, to=targetUid)
132 data = facade.moveOrganizer(targetUid, organizerUid)
133 return DirectResponse.succeed(data=Zuul.marshal(data))
134
136 """
137 gzip an arbitrary string, base64 encode it, and return it
138 """
139 try:
140 compressed = base64.urlsafe_b64encode(zlib.compress(string))
141 except Exception as e:
142 log.exception(e)
143 return DirectResponse.exception(e, 'Unable to compress data')
144 return DirectResponse.succeed(data=Zuul.marshal({'data': compressed}))
145
147 """
148 Base 64 decode a string, then gunzip it and return the result as JSON.
149 The input to this method should be gzipped, base 64 encoded JSON. Base
150 64 encoded strings are allowed to have up to 2 '='s of padding. The zenoss
151 Ext router eats these, so there is some logic to try padding them back into
152 the string should initial decoding fail.
153 """
154 data = ''
155 for pad in ('', '=', '=='):
156 try:
157 data = zlib.decompress(base64.urlsafe_b64decode(string + pad))
158 break
159 except Exception as e:
160 if pad == '==':
161 log.exception(e)
162 return DirectResponse.exception(e, 'Unable to decompress data')
163 return DirectResponse.succeed(data=Zuul.marshal({'data': data}))
164
166 """
167 Abstract method for child classes to use to get their facade
168 """
169 raise NotImplementedError("You must implement the _getFacade method")
170
172 """
173 Server side method for asynchronous tree calls. Retrieves
174 the immediate children of the node specified by "id"
175
176 NOTE: our convention on the UI side is if we are asking
177 for the root node then return the root and its children
178 otherwise just return the children
179
180 @type id: string
181 @param id: The uid of the node we are getting the children for
182 @rtype: [dictionary]
183 @return: Object representing the immediate children
184 """
185 showEventSeverityIcons = self.context.dmd.UserInterfaceSettings.getInterfaceSettings().get('showEventSeverityIcons')
186 facade = self._getFacade()
187 currentNode = facade.getTree(id)
188
189 keys = ('id', 'path', 'uid', 'iconCls', 'text', 'hidden', 'leaf') + additionalKeys
190
191
192 childNodes = list(currentNode.children)
193 if showEventSeverityIcons:
194 uuids = [n.uuid for n in childNodes if n.uuid]
195 zep = Zuul.getFacade('zep', self.context.dmd)
196
197 if uuids:
198 severities = zep.getWorstSeverity(uuids)
199 for child in childNodes:
200 if child.uuid:
201 child.setSeverity(zep.getSeverityName(severities.get(child.uuid, 0)).lower())
202
203 children = []
204
205 for child in childNodes:
206 childData = Marshaller(child).marshal(keys)
207
208
209
210
211
212 organizer = child._get_object()
213
214 hasChildren = any((o['meta_type'] for o in organizer._objects if o['meta_type'] == organizer.meta_type))
215
216 if "report" not in organizer.meta_type.lower() and not hasChildren:
217 childData['children'] = []
218 children.append(childData)
219 children.sort(key=lambda e: (e['leaf'], e['uid'].lower()))
220 obj = currentNode._object._unrestrictedGetObject()
221
222
223 primaryId = obj.getDmdRoot(obj.dmdRootName).getPrimaryId()
224 if id == primaryId:
225 root = Marshaller(currentNode).marshal(keys)
226 root['children'] = children
227 return [root]
228 return children
229
231 """
232 @rtype: DirectResponse
233 @return:
234 - Properties:
235 - B{exists} - Returns true if we can find the object specified by the uid
236
237 """
238 from Products.Zuul.facades import ObjectNotFoundException
239 facade = self._getFacade()
240 try:
241 facade._getObject(uid)
242 exists = True
243 except ObjectNotFoundException:
244 exists = False
245 return DirectResponse(success=True, exists=exists)
246
248 """
249 We can not delete top level UID's. For example:
250 - '/zport/dmd/Processes' this will return False (we can NOT delete)
251 - '/zport/dmd/Processes/Child' will return True
252 (we can delete this)
253 """
254
255 levels = len(uid.split('/'))
256 return levels > 4
257