Ejemplo n.º 1
0
 def _Connect(self,
              username,
              password=None,
              ssh_keys=None,
              enable_password=None,
              ssl_cert_set=None):
     _ = ssl_cert_set
     self._connection = pexpect_connection.ParamikoSshConnection(
         self.loopback_ipv4,
         username,
         password,
         self._success,
         timeout=self.timeout_connect,
         find_prompt=True,
         ssh_keys=ssh_keys,
         enable_password=enable_password)
     try:
         self._connection.Connect()
         self._DisablePager()
         self.connected = True
     except pexpect_connection.ConnectionError as e:
         self.connected = False
         raise exceptions.ConnectError(e)
     except pexpect_connection.TimeoutError as e:
         self.connected = False
         raise exceptions.ConnectError(
             'Timed out connecting to %s(%s) after '
             '%s seconds.' % (self.host, self.loopback_ipv4, str(e)))
Ejemplo n.º 2
0
 def _DisablePager(self):
     """Disables the pager."""
     try:
         self._connection.child.send('\r')
         self._connection.child.expect(r'\r\n',
                                       timeout=self.timeout_connect)
         self._connection.child.expect(self._connection.re_prompt,
                                       timeout=self.timeout_connect,
                                       searchwindowsize=128)
         self._connection.child.send('terminal length 0\r')
         pindex = self._connection.child.expect(
             [
                 self._connection.re_prompt,
                 r'Command authorization failed\.'
             ],
             timeout=self.timeout_connect)
         if pindex == 1:
             self.connected = False
             raise exceptions.ConnectError(
                 'terminal length 0 command denied.')
         # Pause momentarily to avoid a TAC+ packet drop.
         time.sleep(0.5)
     except (pexpect.EOF, pexpect.TIMEOUT) as e:
         self.connected = False
         raise exceptions.ConnectError('%s: %s' % (e.__class__, str(e)))
     logging.debug('terminal length set to 0')
Ejemplo n.º 3
0
 def _Connect(self,
              username=None,
              password=None,
              ssh_keys=None,
              enable_password=None,
              ssl_cert_set=None):
     _ = enable_password, ssl_cert_set
     self._connection = pexpect_connection.ParamikoSshConnection(
         self.loopback_ipv4,
         username,
         password,
         self._success,
         timeout=self.timeout_connect,
         find_prompt=True,
         ssh_keys=ssh_keys,
         # Brocade case 1101014 - \n\r\0 newlines in some 'tm voq' outputs.
         ssh_client=self.ssh_client,
         find_prompt_prefix=r'(?:^|\n|\n\r\0)')
     try:
         self._connection.Connect()
         self._DisablePager()
         self.connected = True
     except pexpect_connection.ConnectionError, e:
         self.connected = False
         raise exceptions.ConnectError(e)
Ejemplo n.º 4
0
Archivo: hp.py Proyecto: tqangxl/ldpush
class HpDevice(base_device.BaseDevice):
  """A base device model for Hewlett-Packard ProCurve switches."""

  RE_INVALID = re.compile(r'^(Invalid|Ambiguous) input:', re.I | re.M)
  RE_PAGER = re.compile(r'-- MORE --, next page: Space, next line: Enter, '
                        'quit: Control-C')

  def __init__(self, **kwargs):
    self.vendor_name = 'hp'
    super(HpDevice, self).__init__(**kwargs)

    # The response regexp indicating connection success.
    self._success = r'ProCurve .*[Ss]witch'

  def _Connect(self, username, password=None, ssh_keys=None,
               enable_password=None, ssl_cert_set=None):
    # Quieten pylint.
    _ = ssl_cert_set
    self._connection = pexpect_connection.HpSshFilterConnection(
        self.loopback_ipv4, username, password, success=self._success,
        timeout=self.timeout_connect, find_prompt=True, ssh_keys=ssh_keys,
        enable_password=enable_password)
    try:
      self._connection.Connect()
      self._DisablePager()
    except pexpect_connection.ConnectionError, e:
      self.connected = False
      raise exceptions.ConnectError(e)
    except pexpect_connection.TimeoutError, e:
      self.connected = False
      raise exceptions.ConnectError('Timed out connecting to %s(%s) after '
                                    '%s seconds.' %
                                    (self.host, self.loopback_ipv4, str(e)))
Ejemplo n.º 5
0
 def _DisablePager(self):
     """Disables the paging."""
     try:
         self._connection.child.send('no paging\r')
         self._connection.child.expect(self._connection.re_prompt,
                                       timeout=self.timeout_connect,
                                       searchwindowsize=128)
     except (pexpect.EOF, pexpect.TIMEOUT) as e:
         self.connected = False
         raise exceptions.ConnectError('%s: %s' % (e.__class__, str(e)))
     logging.debug('Disabled paging on aruba device')
Ejemplo n.º 6
0
class BrocadeDevice(base_device.BaseDevice):
    """A common superclass for Brocade devices."""

    verboten_commands = (
        'monitor ',
        'terminal length ',
        'terminal monitor',
        'page-display',
        'quit',
        'exit',
    )

    verboten_config = ('quit', )
    disable_pager_command = ''

    def __init__(self, **kwargs):
        self.ssh_client = kwargs.pop('ssh_client', None)
        super(BrocadeDevice, self).__init__(**kwargs)
        self._success = r'(?:^|\n)([A-Za-z0-9@\.\-]+[>#])'

    def _Connect(self,
                 username=None,
                 password=None,
                 ssh_keys=None,
                 enable_password=None,
                 ssl_cert_set=None):
        _ = enable_password, ssl_cert_set
        self._connection = pexpect_connection.ParamikoSshConnection(
            self.loopback_ipv4,
            username,
            password,
            self._success,
            timeout=self.timeout_connect,
            find_prompt=True,
            ssh_keys=ssh_keys,
            # Brocade case 1101014 - \n\r\0 newlines in some 'tm voq' outputs.
            ssh_client=self.ssh_client,
            find_prompt_prefix=r'(?:^|\n|\n\r\0)')
        try:
            self._connection.Connect()
            self._DisablePager()
            self.connected = True
        except pexpect_connection.ConnectionError, e:
            self.connected = False
            raise exceptions.ConnectError(e)
        except pexpect_connection.TimeoutError, e:
            self.connected = False
            raise exceptions.ConnectError(
                'Timed out connecting to %s(%s) after '
                '%s seconds.' % (self.host, self.loopback_ipv4, str(e)))
Ejemplo n.º 7
0
Archivo: hp.py Proyecto: tqangxl/ldpush
 def _Connect(self, username, password=None, ssh_keys=None,
              enable_password=None, ssl_cert_set=None):
   # Quieten pylint.
   _ = ssl_cert_set
   self._connection = pexpect_connection.HpSshFilterConnection(
       self.loopback_ipv4, username, password, success=self._success,
       timeout=self.timeout_connect, find_prompt=True, ssh_keys=ssh_keys,
       enable_password=enable_password)
   try:
     self._connection.Connect()
     self._DisablePager()
   except pexpect_connection.ConnectionError, e:
     self.connected = False
     raise exceptions.ConnectError(e)
Ejemplo n.º 8
0
    def Connect(self,
                username,
                password=None,
                ssh_keys=None,
                enable_password=None,
                ssl_cert_set=None):
        """Sets up a connection to the device.

    Concrete classes must implement _Connect() instead, with the same arguments.

    Concrete classes are expected not to disconnect the connection until it
    is cleaned-up by Disconnect().  A generic exception handler at the top-
    level should ensure sessions have an opportunity to be cleaned-up upon
    abnormal program termination.

    Args:
      username: A string, the username (role account) to use.
      password: A string, the password to use (optional; may be None).
      ssh_keys: A tuple of strings, SSH private keys (optional; may be None).
      enable_password: A string, an optional enable password (may be None).
      ssl_cert_set: An optional SSLCertificateSet protobuf (may be None).

    Raises:
      exceptions.ConnectError: the connection could not be established.
      exceptions.AuthenticationError: A device authentication error occurred, or
        neither a password nor an SSH private key was supplied.
    """
        # Either an SSH key or password must be supplied for authentication.
        if (password is None and not ssh_keys and not ssl_cert_set
                and not FLAGS.use_ssh_agent):
            raise exceptions.AuthenticationError(
                'Cannot connect. No authentication information provided to device '
                'Connect method.')

        self._username = username
        self._password = password
        self._ssh_keys = ssh_keys or ()
        self._enable_password = enable_password
        self._ssl_cert_set = ssl_cert_set

        if not self.loopback_ipv4 and not self.accessproxy_device_dict:
            raise exceptions.ConnectError(
                'Device %r, or any access proxies, need to have an IPv4 '
                'management address.' % self.host)

        logging.debug('In BaseDevice.Connect, host is %s, _connected is %s',
                      self.host, self._connected)
        while not self.connected:
            try:
                if self._host_status:
                    logging.debug('CONNECTING %s(%s)', self.host,
                                  self.loopback_ipv4)
                    self._Connect(username,
                                  password=password,
                                  ssh_keys=self._ssh_keys,
                                  enable_password=enable_password,
                                  ssl_cert_set=ssl_cert_set)
                    self.connected = True
                    logging.debug('CONNECTED %s(%s)', self.host,
                                  self.loopback_ipv4)
                    self._last_failure_time = None
                else:
                    self._HostDownPrepareConnect()
            except (exceptions.ConnectError,
                    exceptions.AuthenticationError), e:
                logging.error('CONNECT FAILURE %s(%s)', self.host,
                              self.loopback_ipv4)
                self._host_status = False
                self.__exc = e
                raise
Ejemplo n.º 9
0
def Connect(hostname,
            username,
            password=None,
            port=22,
            ssh_keys=(),
            timeout=TIMEOUT_DEFAULT):
    """Makes a paramiko SSH connection to a device.

  Args:
    hostname: A string, the hostname or IP address to connect to.
    username: A string, the username to use on the connection.
    password: A string, the password to use on the connection.
    port: An int, the port number to connect to.
    ssh_keys: A tuple of strings, SSH private keys (optional; may be None).
    timeout: A float, the number of seconds before a connection times out.

  Returns:
    A paramiko.SSHClient() instance
  """

    options = SshOptions()
    hostname, port, username = options.Lookup(hostname, port, username)
    ssh_client = None

    def RaiseError(e, msg):
        """Raises an exception, disconnecting the SSH client.

    Args:
      e: An Exception.
      msg: An object, exception arguments.
    """
        raise e(msg)

    try:
        ssh_client = paramiko.SSHClient()
        # Always auto-add remote SSH host keys.
        ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh_client.load_system_host_keys()
        # Connect using paramiko with a timeout parameter (requires paramiko 1.7)
        if ssh_keys:
            pkeys = []
            for key in ssh_keys:
                logging.debug(
                    'Using SSH private key for device authentication.')
                # Use a virtual temporary file to store the key.
                ssh_key_fileobj = cStringIO.StringIO()
                ssh_key_fileobj.write(key)
                ssh_key_fileobj.reset()
                try:
                    pkeys.append(paramiko.DSSKey(file_obj=ssh_key_fileobj))
                    logging.debug('Using SSH DSA key for %r', hostname)
                except (IndexError, paramiko.SSHException) as e:
                    if (isinstance(e, IndexError)
                            or 'not a valid DSA private key file' in str(e)):
                        ssh_key_fileobj.reset()
                        try:
                            logging.debug('Using SSH RSA key for %r', hostname)
                            pkeys.append(
                                paramiko.RSAKey(file_obj=ssh_key_fileobj))
                        except (IndexError, paramiko.SSHException) as e:
                            raise exceptions.AuthenticationError(str(e))
                    else:
                        raise exceptions.ConnectError('SSHException: %s' %
                                                      str(e))
        else:
            logging.debug('Using password for %r', hostname)
            pkeys = [None]
        for pkey in pkeys:
            saved_exception = None
            try:
                ssh_client.connect(hostname=hostname,
                                   port=port,
                                   username=username,
                                   password=password,
                                   pkey=pkey,
                                   timeout=timeout,
                                   allow_agent=FLAGS.use_ssh_agent,
                                   look_for_keys=False)
                break
            except (paramiko.AuthenticationException,
                    paramiko.SSHException) as e:
                saved_exception = e
        if saved_exception is not None:
            raise saved_exception  # pylint: disable=raising-bad-type
        transport = ssh_client.get_transport()
        # Sometimes we have to authenticate a second time, eg. on Force10
        # we always fail the first authentication (if we try pkey + pass,
        # the pass succeeds; but if we do pass only, we have to do it
        # twice).  connect() above will have authenticated once.
        if not transport.is_authenticated():
            if pkeys != [None]:
                for pkey in pkeys:
                    try:
                        transport.auth_publickey(username, pkey)
                        break
                    except paramiko.SSHException:
                        pass
        if not transport.is_authenticated():
            if password is not None:
                try:
                    transport.auth_password(username, password)
                except paramiko.SSHException:
                    pass
        if not transport.is_authenticated():
            msg = 'Not authenticated after two attempts on %r' % hostname
            RaiseError(exceptions.ConnectError, msg)
    except EOFError:
        msg = 'EOFError connecting to: %r' % hostname
        RaiseError(exceptions.ConnectError, msg)
    except paramiko.AuthenticationException as e:
        msg = 'Authentication error connecting to %s: %s' % (hostname, str(e))
        RaiseError(exceptions.AuthenticationError, msg)
    except paramiko.SSHException as e:
        msg = 'SSHException connecting to %s: %s' % (hostname, str(e))
        RaiseError(exceptions.ConnectError, msg)
    except socket.timeout as e:
        msg = 'Timed-out while connecting to %s: %s' % (hostname, str(e))
        RaiseError(exceptions.ConnectError, msg)
    except socket.error as e:
        msg = 'Socket error connecting to %r: %s %s' % (hostname, e.__class__,
                                                        e)
        RaiseError(exceptions.ConnectError, msg)

    return ssh_client
Ejemplo n.º 10
0
    def _Cmd(self,
             command,
             mode=None,
             merge_stderr_first=False,
             send=None,
             require_low_chanid=False):
        response = ''
        retries_left = 1
        while True:
            try:
                chan = self._ssh_client.get_transport().open_session()
                chan.settimeout(self.timeout_response)
                if require_low_chanid and chan.remote_chanid > _LOW_CHANID_THRESHOLD:
                    # We should not be having multiple channels open. If we do,
                    # close them before proceeding.
                    logging.error(
                        'Remote ssh channel id %d exceeded %d when opening session to '
                        '%s(%s), reconnecting.', chan.remote_chanid,
                        _LOW_CHANID_THRESHOLD, self.host, self.loopback_ipv4)
                    self.Disconnect()
                    self.Connect(self._username, self._password,
                                 self._ssh_keys, self._enable_password)
                    chan = self._ssh_client.get_transport().open_session()
                chan.exec_command(command)
                stdin = chan.makefile('wb', -1)
                stdout = chan.makefile('rb', -1)
                stderr = chan.makefile_stderr('rb', -1)
                if send is not None:
                    stdin.write(send)
                stdout_data = stdout.read()
                stderr_data = stderr.read()

                # Request channel close by remote peer.
                chan.close()
                break
            except paramiko.SSHException as e:
                msg = str(e)
                logging.error('%s(%s) Cmd(%r, mode=%r): %s', self.host,
                              self.loopback_ipv4, command, mode, msg)
                raise exceptions.CmdError(msg)
            except AttributeError:
                # This occurs when self._ssh_client becomes None after a Paramiko
                # failure. Pause momentarily, try to reconnect and loop to resend
                # the command.
                time.sleep(0.25)
                try:
                    if retries_left:
                        self._Connect(self._username, self._password,
                                      self._ssh_keys)
                        retries_left -= 1
                        continue
                    else:
                        raise exceptions.CmdError(
                            'Failed to exec_command after retry.')
                except paramiko.SSHException as e:
                    msg = str(e)
                    logging.error('%s(%s) Cmd(%r, mode=%r): %s', self.host,
                                  self.loopback_ipv4, command, mode, msg)
                    raise exceptions.ConnectError(msg)
            except Exception as e:
                # Paramiko may raise any exception, so catch and log it here.
                msg = '%s:%s(%s) Cmd(%r, mode=%r): %s: %s' % (
                    type(e), self.host, self.loopback_ipv4, command, mode,
                    e.__class__.__name__, str(e))
                logging.exception(msg)
                raise exceptions.CmdError('%s: %s' %
                                          (e.__class__.__name__, str(e)))

        # Remove stderr lines started with 'waiting for'.
        if stderr_data and not merge_stderr_first:
            out = []
            for l in stderr_data.splitlines():
                if not l.startswith('waiting for'):
                    out.append(l)
            stderr_data = '\n'.join(out)

        # Marshal the response from the stdout/err channels and handle errors.
        if stderr_data and not merge_stderr_first:
            raise exceptions.CmdError(stderr_data)
        elif stdout_data:
            if merge_stderr_first and stderr_data:
                response = stderr_data
            response += stdout_data
        else:
            # Sometimes, a command (e.g., 'show system license keys') returns
            # nothing.  This can mean that the channel went away on us, and we
            # got no data back (and no error).
            if self.connected:
                logging.warn('Both STDOUT and STDERR empty after %s on %s(%s)',
                             repr(command), self.host, self.loopback_ipv4)
            else:
                raise exceptions.CmdError(
                    'Connection to %s(%s) was terminated.' %
                    (self.host, self.loopback_ipv4))
        return response