Package Products :: Package ZenWidgets :: Package browser :: Package quickstart :: Module views |
[hide private]
[frames] | no frames]

# Source Code for Module Products.ZenWidgets.browser.quickstart.views

      1  ###########################################################################
      2  #
      3  # This program is part of Zenoss Core, an open source monitoring platform.
      4  # Copyright (C) 2007, Zenoss Inc.
      5  #
      6  # This program is free software; you can redistribute it and/or modify it
      7  # under the terms of the GNU General Public License version 2 as published by
      8  # the Free Software Foundation.
      9  #
     10  # For complete information please visit: http://www.zenoss.com/oss/
     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
     23  _is_network = lambda x: bool(re.compile(r'^(\d+\.){3}\d+\/\d+$').search(x))
     24  _is_range = lambda x: bool(re.compile(r'^(\d+\.){3}\d+\-\d+$').search(x))
     25
     26 -class QuickstartBase(BrowserView):
     27      """
     28      Standard macros for the quickstart.
     29      """
     30      template = ZopeTwoPageTemplateFile('templates/quickstart_macros.pt')
     31
     32 -    def __getitem__(self, key):
     33          return self.template.macros[key]
     34
     35
     36 -class OutlineView(BrowserView):
     37      """
     38      Displays the steps the user will soon be completing. The anticipation!
     39      """
     40      __call__ = ZopeTwoPageTemplateFile('templates/outline.pt')
     41
     42
     43 -class CreateUserView(BrowserView):
     44      """
     45      Creates the initial user and sets the admin password.
     46      """
     47      __call__ = ZopeTwoPageTemplateFile('templates/createuser.pt')
     48
     49
     50 -class DeviceAddView(BrowserView):
     51      """
     52      Specify devices to be added.
     53      """
     54      @json
     55 -    def default_communities(self):
     56          """
     57          Format the value of Devices.Discovered.zSnmpCommunities for a textarea
     58          """
     59          devclass = self.context.dmd.Devices.Discovered.primaryAq()
     60          return '\n'.join(devclass.zSnmpCommunities)
     61
     62 -    def _assemble_types_list(self):
     63          """
     64          Walks all device classes building a list of description/protocol pairs.
     65          """
     66          ALLOWED_PROTOCOLS = ('SSH', 'SNMP', 'WMI')
     67          devclass = self.context.dmd.Devices
     68          orgs = devclass.getSubOrganizers()
     69          types = []
     70          for org in orgs:
     71              # Skip it if it doesn't have types registered
     72              if not hasattr(aq_base(org), 'devtypes') or not org.devtypes:
     73                  continue
     74              for t in org.devtypes:
     75                  desc, ptcl = t
     76                  # Both must be defined
     77                  if not ptcl or not desc: continue
     78                  # We only care about orgs with acceptable protocols
     79                  if ptcl not in ALLOWED_PROTOCOLS: continue
     80                  types.append((org.getOrganizerName(), desc, ptcl))
     81          return types
     82
     83      @json
     84 -    def device_types(self):
     85          """
     86          Build an object for populating an Ext ComboBox representing "device
     87          types," which should exactly correspond to DeviceClasses in the system.
     88
     89          This method iterates over a predetermined list of types we might want
     90          to see and checks each DeviceClass for existence (i.e., is the
     91          appropriate ZenPack installed?).
     92          """
     93          # Turn them into the dictionary format expected
     94          types = {'win':[], 'ssh':[], 'snmp':[]}
     95          for t in self._assemble_types_list():
     96              if   t[2]=='WMI':  types['win'].append(t)
     97              elif t[2]=='SNMP': types['snmp'].append(t)
     98              elif t[2]=='SSH':  types['ssh'].append(t)
     99
    100          def dev_class_exists(path):
    101              """
    102              Return a boolean indicating whether the specified DeviceClass
    103              exists.
    104              """
    105              try:
    106                  self.context.unrestrictedTraverse(
    107                      '/zport/dmd/Devices' + path)
    108              except AttributeError:
    109                  return False
    110              else:
    111                  return True
    112
    113          def format_type(credtype, classpath, description, protocol):
    114              """
    115              Turn information representing a device class into a dictionary of
    116              the format our ComboBox expects.
    117              """
    118              value = '%s_%s' % (classpath, credtype)
    119              return dict(value=value,
    120                          shortdesc="%s (%s)" % (description, protocol),
    121                          description=description, protocol=protocol)
    122
    123          # Iterate over all types
    124          response = []
    125          for credtype, devtypes in types.iteritems():
    126              for devtype in devtypes:
    127                  # Check for existence
    128                  if dev_class_exists(devtype[0]):
    129                      # Exists, so add it to the list
    130                      response.append(format_type(credtype, *devtype))
    131
    132          # Sort alphabetically by description
    133          response.sort(key=lambda x:x['description'])
    134
    135          # Final response needs an object under a defined root, in this case
    136          # "types"
    137          return dict(types=response)
    138
    139
    140      @Ext.form_action
    141 -    def autodiscovery(self):
    142          response = Ext.FormResponse()
    143          submitted = self.request.form.get('network', [])
    144          if isinstance(submitted, basestring):
    145              submitted = [submitted]
    146          zProperties = {
    147              'zCommandUsername': self.request.form.get('sshusername'),
    148              'zCommandPassword': self.request.form.get('sshpass'),
    149              'zWinUser': self.request.form.get('winusername'),
    150              'zWinPassword': self.request.form.get('winpass'),
    151              'zSnmpCommunities': self.request.form.get('snmpcommunities').splitlines()
    152          }
    153          # Split rows into networks and ranges
    154          nets = []
    155          ranges = []
    156          for row in submitted:
    157              if _is_network(row): nets.append(row)
    158              elif _is_range(row): ranges.append(row)
    159          if not nets and not ranges:
    160              response.error('network',
    161                             'You must enter at least one network or IP range.')
    162          if nets:
    163              for net in nets:
    164                  # Make the network if it doesn't exist, so zendisc has
    165                  # something to discover
    166                  _n = self.context.dmd.Networks.createNet(net)
    167              try:
    168                  self.context.JobManager.addJob(
    169                      AutoDiscoveryJob,
    170                      nets=nets,
    171                      zProperties=zProperties)
    172              except:
    173                  response.error('network', 'There was an error scheduling this '
    174                                 'job. Please check your installation and try '
    175                                 'again.')
    176              else:
    177                  IMessageSender(self.context).sendToUser(
    178                      'Autodiscovery Task Created',
    179                      'Discovery of the following networks is in progress: %s' % (
    180                          ', '.join(ranges))
    181                  )
    182          if ranges:
    183              # Ranges can just be sent to zendisc, as they are merely sets of
    184              # IPs
    185              try:
    186                  self.context.JobManager.addJob(
    187                      AutoDiscoveryJob,
    188                      ranges=ranges,
    189                      zProperties=zProperties)
    190              except:
    191                  response.error('network', 'There was an error scheduling this '
    192                                 'job. Please check your installation and try '
    193                                 'again.')
    194              else:
    195                  IMessageSender(self.context).sendToUser(
    196                      'Autodiscovery Task Created',
    197                      'Discovery of the following IP ranges is in progress: %s' % (
    198                          ', '.join(ranges))
    199                  )
    200
    201
    202          response.redirect('/zport/dmd')
    203          return response
    204
    205
    206      @Ext.form_action
    207 -    def manual(self):
    208          # Pull all the device name keys
    209          response = Ext.FormResponse()
    210          devs = filter(lambda x:x.startswith('device_'),
    211                        self.request.form.keys())
    212          # Make sure we have at least one device name
    213          devnames = filter(lambda x:bool(self.request.form.get(x)), devs)
    214          if not devnames:
    215              response.error('device_0',
    216                             'You must enter at least one hostname/IP.')
    217              return response
    218          # Create jobs based on info passed
    219          for k in devs:
    220              # Ignore empty device names
    221              if not self.request.form.get(k): continue
    222              idx = k.split('_')[1]
    223              devclass, type_ = self.request.form.get(
    224                  'deviceclass_%s' % idx).split('_')
    225              # Set zProps based on type
    226              if type_=='ssh':
    227                  zProps = {
    228                      'zCommandUsername': self.request.form.get('sshuser_%s' % idx),
    229                      'zCommandPassword': self.request.form.get(
    230                          'sshpass_%s' % idx),
    231                  }
    232              elif type_=='win':
    233                  zProps = {
    234                      'zWinUser': self.request.form.get('winuser_%s' % idx),
    235                      'zWinPassword': self.request.form.get('winpass_%s' % idx),
    236                  }
    237              elif type_=='snmp':
    238                  zProps = {
    239                      'zSnmpCommunities': self.request.form.get(
    240                          'snmpcomm_%s' % idx
    241                      ).splitlines()
    242                  }
    243              perfConf = self.context.Monitors.getPerformanceMonitor('localhost')
    244              perfConf.addDeviceCreationJob(deviceName=self.request.form.get(k),
    245                  devicePath=devclass, zProperties=zProps, discoverProto='auto')
    246          devnames = [self.request.form.get(dev) for dev in devs]
    247          IMessageSender(self.context).sendToUser(
    248              'Devices Added',
    249              'Modeling of the following devices has been scheduled: %s' % (
    250                  ', '.join(filter(None, devnames))
    251              )
    252          )
    253          response.redirect('/zport/dmd')
    254          return response
    255