1
2
3
4
5
6
7
8
9
10
11
12
13
14 import re
15 from Acquisition import aq_base
16 from Products.Five.browser import BrowserView
17 from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile
18 from Products.ZenModel.IpNetwork import AutoDiscoveryJob
19 from Products.ZenWidgets.messaging import IMessageSender
20 from Products.ZenUtils import Ext
21 from Products.ZenUtils.jsonutils import json
22 from Products.ZenMessaging.actions import sendUserAction
23 from Products.ZenMessaging.actions.constants import ActionTargetType, ActionName
24
25 _is_network = lambda x: bool(re.compile(r'^(\d+\.){3}\d+\/\d+$').search(x))
26 _is_range = lambda x: bool(re.compile(r'^(\d+\.){3}\d+\-\d+$').search(x))
29 """
30 Standard macros for the quickstart.
31 """
32 template = ZopeTwoPageTemplateFile('templates/quickstart_macros.pt')
33
36
39 """
40 Displays the steps the user will soon be completing. The anticipation!
41 """
42 __call__ = ZopeTwoPageTemplateFile('templates/outline.pt')
43
46 """
47 Creates the initial user and sets the admin password.
48 """
49 __call__ = ZopeTwoPageTemplateFile('templates/createuser.pt')
50
53 """
54 Specify devices to be added.
55 """
56 @json
58 """
59 Format the value of Devices.Discovered.zSnmpCommunities for a textarea
60 """
61 devclass = self.context.dmd.Devices.Discovered.primaryAq()
62 return '\n'.join(devclass.zSnmpCommunities)
63
65 """
66 Walks all device classes building a list of description/protocol pairs.
67 """
68 ALLOWED_PROTOCOLS = ('SSH', 'SNMP', 'WMI')
69 devclass = self.context.dmd.Devices
70 orgs = devclass.getSubOrganizers()
71 types = []
72 for org in orgs:
73
74 if not hasattr(aq_base(org), 'devtypes') or not org.devtypes:
75 continue
76 for t in org.devtypes:
77 try:
78 desc, ptcl = t
79 except ValueError:
80 continue
81
82
83 if not ptcl or not desc:
84 continue
85
86
87 if ptcl not in ALLOWED_PROTOCOLS: continue
88 types.append((org.getOrganizerName(), desc, ptcl))
89 return types
90
91 @json
93 """
94 Build an object for populating an Ext ComboBox representing "device
95 types," which should exactly correspond to DeviceClasses in the system.
96
97 This method iterates over a predetermined list of types we might want
98 to see and checks each DeviceClass for existence (i.e., is the
99 appropriate ZenPack installed?).
100 """
101
102 types = {'win':[], 'ssh':[], 'snmp':[]}
103 for t in self._assemble_types_list():
104 if t[2]=='WMI': types['win'].append(t)
105 elif t[2]=='SNMP': types['snmp'].append(t)
106 elif t[2]=='SSH': types['ssh'].append(t)
107
108 def dev_class_exists(path):
109 """
110 Return a boolean indicating whether the specified DeviceClass
111 exists.
112 """
113 try:
114 self.context.unrestrictedTraverse(
115 '/zport/dmd/Devices' + path)
116 except AttributeError:
117 return False
118 else:
119 return True
120
121 def format_type(credtype, classpath, description, protocol):
122 """
123 Turn information representing a device class into a dictionary of
124 the format our ComboBox expects.
125 """
126 value = '%s_%s' % (classpath, credtype)
127 return dict(value=value,
128 shortdesc="%s (%s)" % (description, protocol),
129 description=description, protocol=protocol)
130
131
132 response = []
133 for credtype, devtypes in types.iteritems():
134 for devtype in devtypes:
135
136 if dev_class_exists(devtype[0]):
137
138 response.append(format_type(credtype, *devtype))
139
140
141 response.sort(key=lambda x:x['description'])
142
143
144
145 return dict(types=response)
146
147
148 @Ext.form_action
150 response = Ext.FormResponse()
151 submitted = self.request.form.get('network', [])
152 if isinstance(submitted, basestring):
153 submitted = [submitted]
154 zProperties = {
155 'zCommandUsername': self.request.form.get('sshusername'),
156 'zCommandPassword': self.request.form.get('sshpass'),
157 'zWinUser': self.request.form.get('winusername'),
158 'zWinPassword': self.request.form.get('winpass'),
159 'zSnmpCommunities': self.request.form.get('snmpcommunities').splitlines()
160 }
161
162 nets = []
163 ranges = []
164 for row in submitted:
165 if _is_network(row): nets.append(row)
166 elif _is_range(row): ranges.append(row)
167 if not nets and not ranges:
168 response.error('network',
169 'You must enter at least one network or IP range.')
170 if nets:
171 for net in nets:
172
173
174 _n = self.context.dmd.Networks.createNet(net)
175 try:
176 self.context.JobManager.addJob(
177 AutoDiscoveryJob,
178 nets=nets,
179 zProperties=zProperties)
180 except:
181 response.error('network', 'There was an error scheduling this '
182 'job. Please check your installation and try '
183 'again.')
184 else:
185 IMessageSender(self.context).sendToUser(
186 'Autodiscovery Task Created',
187 'Discovery of the following networks is in progress: %s' % (
188 ', '.join(nets))
189 )
190 if ranges:
191
192
193 try:
194 self.context.JobManager.addJob(
195 AutoDiscoveryJob,
196 ranges=ranges,
197 zProperties=zProperties)
198 except:
199 response.error('network', 'There was an error scheduling this '
200 'job. Please check your installation and try '
201 'again.')
202 else:
203 IMessageSender(self.context).sendToUser(
204 'Autodiscovery Task Created',
205 'Discovery of the following IP ranges is in progress: %s' % (
206 ', '.join(ranges))
207 )
208
209 if sendUserAction:
210 networks = ','.join(nets)
211 ipRanges = ','.join(ranges)
212 sendUserAction(ActionTargetType.Device, 'Autodiscovery',
213 networks=networks, ipRanges=ipRanges)
214
215 response.redirect('/zport/dmd')
216 return response
217
218
219 @Ext.form_action
221
222 response = Ext.FormResponse()
223 devs = filter(lambda x:x.startswith('device_'),
224 self.request.form.keys())
225
226 devnames = filter(lambda x:bool(self.request.form.get(x)), devs)
227 if not devnames:
228 response.error('device_0',
229 'You must enter at least one hostname/IP.')
230 return response
231
232 for k in devs:
233
234 if not self.request.form.get(k): continue
235 idx = k.split('_')[1]
236 devclass, type_ = self.request.form.get(
237 'deviceclass_%s' % idx).split('_')
238
239 if type_=='ssh':
240 zProps = {
241 'zCommandUsername': self.request.form.get('sshuser_%s' % idx),
242 'zCommandPassword': self.request.form.get(
243 'sshpass_%s' % idx),
244 }
245 elif type_=='win':
246 zProps = {
247 'zWinUser': self.request.form.get('winuser_%s' % idx),
248 'zWinPassword': self.request.form.get('winpass_%s' % idx),
249 }
250 elif type_=='snmp':
251 zProps = {
252 'zSnmpCommunities': self.request.form.get(
253 'snmpcomm_%s' % idx
254 ).splitlines()
255 }
256 deviceName = self.request.form.get(k)
257 perfConf = self.context.Monitors.getPerformanceMonitor('localhost')
258 perfConf.addDeviceCreationJob(deviceName=deviceName,
259 devicePath=devclass, zProperties=zProps, discoverProto='auto')
260 if sendUserAction:
261 deviceClassUid = '/Devices' + devclass
262 deviceUid = '/'.join([deviceClassUid, 'devices', deviceName])
263 sendUserAction(ActionTargetType.Device, ActionName.Add,
264 device=deviceUid, deviceClass=deviceClassUid,
265 model=True)
266 devnames = [self.request.form.get(dev) for dev in devs]
267 IMessageSender(self.context).sendToUser(
268 'Devices Added',
269 'Modeling of the following devices has been scheduled: %s' % (
270 ', '.join(filter(None, devnames))
271 )
272 )
273 response.redirect('/zport/dmd')
274 return response
275