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 require
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.ZenMessaging.audit import audit
21 from Products.ZenUtils.Utils import getDisplayType
22 from Products import Zuul
23 import logging
24 log = logging.getLogger(__name__)
28 """
29 A common base class for routers that have a hierarchical tree structure.
30 """
31
32 @require('Manage DMD')
33 - def addNode(self, type, contextUid, id, description=None):
34 """
35 Add a node to the existing tree underneath the node specified
36 by the context UID
37
38 @type type: string
39 @param type: Either 'class' or 'organizer'
40 @type contextUid: string
41 @param contextUid: Path to the node that will
42 be the new node's parent (ex. /zport/dmd/Devices)
43 @type id: string
44 @param id: Identifier of the new node, must be unique in the
45 parent context
46 @type description: string
47 @param description: (optional) Describes this new node (default: None)
48 @rtype: dictionary
49 @return: Marshaled form of the created node
50 """
51 result = {}
52 try:
53 facade = self._getFacade()
54 if type.lower() == 'class':
55 uid = facade.addClass(contextUid, id)
56 audit('UI.Class.Add', uid)
57 else:
58 organizer = facade.addOrganizer(contextUid, id, description)
59 uid = organizer.uid
60 audit(['UI', getDisplayType(organizer), 'Add'], organizer)
61
62 treeNode = facade.getTree(uid)
63 result['nodeConfig'] = Zuul.marshal(treeNode)
64 result['success'] = True
65 except Exception, e:
66 log.exception(e)
67 result['msg'] = str(e)
68 result['success'] = False
69 return result
70
71 @require('Manage DMD')
73 """
74 Deletes a node from the tree.
75
76 B{NOTE}: You can not delete a root node of a tree
77
78 @type uid: string
79 @param uid: Unique identifier of the node we wish to delete
80 @rtype: DirectResponse
81 @return: B{Properties}:
82 - msg: (string) Status message
83 """
84
85 if not self._canDeleteUid(uid):
86 raise Exception('You cannot delete the root node')
87 facade = self._getFacade()
88 node = facade._getObject(uid)
89
90
91
92
93 if isinstance(node, DeviceClass):
94 childBrains = ICatalogTool(node).search((
95 'Products.ZenModel.DeviceClass.DeviceClass',
96 'Products.ZenModel.Device.Device',
97 ))
98 for child in childBrains:
99 audit(['UI', getDisplayType(child), 'Delete'], child.getPath())
100 else:
101 audit(['UI', getDisplayType(node), 'Delete'], node)
102
103 facade.deleteNode(uid)
104 msg = "Deleted node '%s'" % uid
105 return DirectResponse.succeed(msg=msg)
106
108 """
109 Move the organizer uid to be underneath the organizer
110 specified by the targetUid.
111
112 @type targetUid: string
113 @param targetUid: New parent of the organizer
114 @type organizerUid: string
115 @param organizerUid: The organizer to move
116 @rtype: DirectResponse
117 @return: B{Properties}:
118 - data: (dictionary) Moved organizer
119 """
120 facade = self._getFacade()
121 display_type = getDisplayType(facade._getObject(organizerUid))
122 audit(['UI', display_type, 'Move'], organizerUid, to=targetUid)
123 data = facade.moveOrganizer(targetUid, organizerUid)
124 return DirectResponse.succeed(data=Zuul.marshal(data))
125
127 """
128 Abstract method for child classes to use to get their facade
129 """
130 raise NotImplementedError("You must implement the _getFacade method")
131
133 """
134 Server side method for asynchronous tree calls. Retrieves
135 the immediate children of the node specified by "id"
136
137 NOTE: our convention on the UI side is if we are asking
138 for the root node then return the root and its children
139 otherwise just return the children
140
141 @type id: string
142 @param id: The uid of the node we are getting the children for
143 @rtype: [dictionary]
144 @return: Object representing the immediate children
145 """
146 facade = self._getFacade()
147 currentNode = facade.getTree(id)
148
149 keys = ('id', 'path', 'uid', 'iconCls', 'text', 'hidden', 'leaf') + additionalKeys
150
151
152 childNodes = list(currentNode.children)
153 uuids = [n.uuid for n in childNodes if n.uuid]
154 zep = Zuul.getFacade('zep', self.context.dmd)
155 if uuids:
156 severities = zep.getWorstSeverity(uuids)
157 for child in childNodes:
158 if child.uuid:
159 child.setSeverity(zep.getSeverityName(severities.get(child.uuid, 0)).lower())
160
161 children = []
162
163 for child in childNodes:
164 childData = Marshaller(child).marshal(keys)
165 children.append(childData)
166 children.sort(key=lambda e: (e['leaf'], e['uid'].lower()))
167 obj = currentNode._object._unrestrictedGetObject()
168
169
170 primaryId = obj.getDmdRoot(obj.dmdRootName).getPrimaryId()
171 if id == primaryId:
172 root = Marshaller(currentNode).marshal(keys)
173 root['children'] = children
174 return [root]
175 return children
176
178 """
179 We can not delete top level UID's. For example:
180 - '/zport/dmd/Processes' this will return False (we can NOT delete)
181 - '/zport/dmd/Processes/Child' will return True
182 (we can delete this)
183 """
184
185 levels = len(uid.split('/'))
186 return levels > 4
187