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.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
     27 -class QuickstartBase(BrowserView):
     28      """
     29      Standard macros for the quickstart.
     30      """
     31      template = ZopeTwoPageTemplateFile('templates/quickstart_macros.pt')
     32
     33 -    def __getitem__(self, key):
     34          return self.template.macros[key]
     35
     36
     37 -class OutlineView(BrowserView):
     38      """
     39      Displays the steps the user will soon be completing. The anticipation!
     40      """
     41      __call__ = ZopeTwoPageTemplateFile('templates/outline.pt')
     42
     43
     44 -class CreateUserView(BrowserView):
     45      """
     46      Creates the initial user and sets the admin password.
     47      """
     48      __call__ = ZopeTwoPageTemplateFile('templates/createuser.pt')
     49
     50
     51 -class DeviceAddView(BrowserView):
     52      """
     53      Specify devices to be added.
     54      """
     55      @json
     56 -    def default_communities(self):
     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
     63 -    def _assemble_types_list(self):
     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              # Skip it if it doesn't have types registered
     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                  # Both must be defined
     78                  if not ptcl or not desc: continue
     79                  # We only care about orgs with acceptable protocols
     80                  if ptcl not in ALLOWED_PROTOCOLS: continue
     81                  types.append((org.getOrganizerName(), desc, ptcl))
     82          return types
     83
     84      @json
     85 -    def device_types(self):
     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          # Turn them into the dictionary format expected
     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          # Iterate over all types
    125          response = []
    126          for credtype, devtypes in types.iteritems():
    127              for devtype in devtypes:
    128                  # Check for existence
    129                  if dev_class_exists(devtype[0]):
    130                      # Exists, so add it to the list
    131                      response.append(format_type(credtype, *devtype))
    132
    133          # Sort alphabetically by description
    134          response.sort(key=lambda x:x['description'])
    135
    136          # Final response needs an object under a defined root, in this case
    137          # "types"
    138          return dict(types=response)
    139
    140
    141      @Ext.form_action
    142 -    def autodiscovery(self):
    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          # Split rows into networks and ranges
    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                  # Make the network if it doesn't exist, so zendisc has
    166                  # something to discover
    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              # Ranges can just be sent to zendisc, as they are merely sets of
    185              # IPs
    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
    208 -    def manual(self):
    209          # Pull all the device name keys
    210          response = Ext.FormResponse()
    211          devs = filter(lambda x:x.startswith('device_'),
    212                        self.request.form.keys())
    213          # Make sure we have at least one device name
    214          devnames = filter(lambda x:bool(self.request.form.get(x)), devs)
    215          if not devnames:
    216              response.error('device_0',
    217                             'You must enter at least one hostname/IP.')
    218              return response
    219          # Create jobs based on info passed
    220          for k in devs:
    221              # Ignore empty device names
    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              # Set zProps based on type
    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