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