예제 #1
0
파일: brocade.py 프로젝트: wkumari/ldpush
    def _SetConfig(self, destination_file, data, canary):
        # Canarying is not supported on BROCADE.
        if canary:
            raise exceptions.SetConfigCanaryingError(
                '%s devices do not support '
                'configuration canarying.' % self.vendor_name)
        # The result object.
        result = base_device.SetConfigResult()
        # Check for a connection to the Brocade.
        if not self._GetConnected():
            raise exceptions.SetConfigError('Cannot use unless already '
                                            'connected to the device.')

        if destination_file in self.NON_FILE_DESTINATIONS:
            # Use a random remote file name
            file_name = 'push.%s' % os.urandom(8).encode('hex')
        else:
            # Okay, the user is just copying a file, not a configuraiton into either
            # startup-config or running-config, therefore we should use the entire
            # path.
            file_name = destination_file

        # Copy the file to the router using SCP.
        scp = pexpect_connection.ScpPutConnection(host=self.loopback_ipv4,
                                                  username=self._username,
                                                  password=self._password)

        # This is a workaround. Brocade case: 537017.
        # Brocade changed all the filename to lowercases after scp
        file_name = file_name.lower()
        try:
            scp.Copy(data, destination_file='slot1:' + file_name)
        except pexpect_connection.Error, e:
            raise exceptions.SetConfigError(
                'Failed to copy configuration to remote device. %s' % str(e))
예제 #2
0
  def _SetConfig(self, destination_file, data, canary):
    # Canarying is not supported on ASA.
    if canary:
      raise exceptions.SetConfigCanaryingError('%s devices do not support '
                                               'configuration canarying.' %
                                               self.vendor_name)
    # We only support copying to 'running-config' or 'startup-config' on ASA.
    if destination_file not in ('running-config', 'startup-config'):
      raise exceptions.SetConfigError('destination_file argument must be '
                                      '"running-config" or "startup-config" '
                                      'for %s devices.' % self.vendor_name)
    # Result object.
    result = base_device.SetConfigResult()

    # Get the MD5 sum of the file.
    local_digest = hashlib.md5(data).hexdigest()

    try:
      # Get the working path from the remote device
      remote_path = 'nvram:/'
    except exceptions.CmdError as e:
      msg = 'Error obtaining working directory: %s' % e
      logging.error(msg)
      raise exceptions.SetConfigError(msg)

    # Use a random remote file name
    remote_tmpfile = '%s/push.%s' % (
        remote_path.rstrip(), os.urandom(8).encode('hex'))

    # Upload the file to the device.
    scp = pexpect_connection.ScpPutConnection(
        self.loopback_ipv4,
        username=self._username,
        password=self._password)
    try:
      scp.Copy(data, remote_tmpfile)
    except pexpect_connection.Error as e:
      raise exceptions.SetConfigError(
          'Failed to copy configuration to remote device. %s' % str(e))

    # Get the file size on the router.
    try:
      # Get the MD5 hexdigest of the file on the remote device.
      try:
        verify_output = self._Cmd('verify /md5 %s' % remote_tmpfile)
        match = MD5_RE.search(verify_output)
        if match is not None:
          remote_digest = match.group(1)
        else:
          raise exceptions.SetConfigError(
              'The "verify /md5 <filename>" command did not produce '
              'expected results. It returned: %r' % verify_output)
      except exceptions.CmdError as e:
        raise exceptions.SetConfigError(
            'The MD5 hash command on the router did not succed. '
            'The device may not support: "verify /md5 <filename>"')
      # Verify the local_digest and remote_digest are the same.
      if local_digest != remote_digest:
        raise exceptions.SetConfigError(
            'File transfer to remote host corrupted. Local digest: %r, '
            'Remote digest: %r' % (local_digest, remote_digest))

      # Copy the file from flash to the
      # destination(running-config, startup-config).
      # Catch errors that may occur during application, and report
      # these to the user.
      try:
        self._connection.child.send(
            'copy %s %s\r' % (remote_tmpfile, destination_file))
        pindex = self._connection.child.expect(
            [r'Destination filename \[%s\]\?' % destination_file,
             r'%\s*\S*.*',
             r'%Error.*',
             self._connection.re_prompt],
            timeout=self.timeout_act_user)
        if pindex == 0:
          self._connection.child.send('\r')
          try:
            pindex = self._connection.child.expect(
                [r'Invalid input detected',
                 self._connection.re_prompt,
                 r'%Warning:There is a file already existing.*'
                 'Do you want to over write\? \[confirm\]'],
                timeout=self.timeout_act_user)
            if pindex == 0:
              # Search again using findall to get all bad lines.
              bad_lines = re.findall(
                  r'^(.*)$[\s\^]+% Invalid input',
                  self._connection.child.match.string,
                  re.MULTILINE)
              raise exceptions.SetConfigSyntaxError(
                  'Configuration loaded, but with bad lines:\n%s' %
                  '\n'.join(bad_lines))
            if pindex == 2:
              # Don't over-write.
              self._connection.child.send('n')
              raise exceptions.SetConfigError(
                  'Destination file %r already exists, cannot overwrite.'
                  % destination_file)
          except (pexpect.EOF, pexpect.TIMEOUT) as e:
            raise exceptions.SetConfigError(
                'Copied file to device, but did not '
                'receive prompt afterwards. %s %s' %
                (self._connection.child.before, self._connection.child.after))

        elif pindex == 2:
          print "MATCHED 2"
          # The expect does a re.search, search again using findall to get all
          raise exceptions.SetConfigError('Could not copy temporary '
                                          'file to %s.' % destination_file)
      except (pexpect.EOF, pexpect.TIMEOUT) as e:
        raise exceptions.SetConfigError(
            'Attempted to copy to bootflash, but a timeout occurred.')

      # We need to 'write memory' if we are doing running-config.
      if destination_file == 'running-config':
        logging.debug('Attempting to copy running-config to startup-config '
                     'on %s(%s)', self.host, self.loopback_ipv4)
        try:
          self._Cmd('wr mem')
        except exceptions.CmdError as e:
          raise exceptions.SetConfigError('Failed to write startup-config '
                                          'for %s(%s). Changes applied. '
                                          'Error was: %s' %
                                          (self.host, self.loopback_ipv4,
                                           str(e)))
    finally:
      try:
        self._DeleteFile(remote_tmpfile)
      except DeleteFileError as e:
        result.transcript = 'SetConfig warning: %s' % str(e)
        logging.warn(result.transcript)

    # And finally, return the result text.
    return result