Exemple #1
0
 def createVirtualDevice(self):
     self.banner = 'Welcome to %s!\n' % self.hostname
     self.prompt = self.hostname + '> '
     self.device = VirtualDevice(self.hostname, echo=True)
     ls_response = '-rw-r--r--  1 sab  nmc    1628 Aug 18 10:02 file'
     self.device.add_command('ls', ls_response)
     self.device.add_command('df', 'foobar')
     self.device.add_command('exit', '')
     self.device.add_command('this-command-causes-an-error',
                             '\ncommand not found')
Exemple #2
0
    def __init__(self, device=None, **kwargs):
        """
        @note: Also supports all keyword arguments that L{Protocol} supports.

        @keyword device: The L{Exscript.emulators.VirtualDevice} with
            which to communicate.
        """
        Protocol.__init__(self, **kwargs)
        self.device = device
        self.init_done = False
        self.cancel = False
        self.response = None
        if not self.device:
            self.device = VirtualDevice('dummy', strict=False)
Exemple #3
0
    def __init__(self, device=None, **kwargs):
        """
        .. HINT::
            Also supports all keyword arguments that :class:`Protocol` supports.

        :keyword device: The :class:`Exscript.emulators.VirtualDevice` with
            which to communicate.
        """
        Protocol.__init__(self, **kwargs)
        self.device = device
        self.init_done = False
        self.cancel = False
        self.response = None
        if not self.device:
            self.device = VirtualDevice('dummy', strict=False)
Exemple #4
0
 def __init__(self,
              hostname,
              echo=True,
              login_type=VirtualDevice.LOGIN_TYPE_BOTH,
              strict=True,
              banner=None):
     thebanner = iosbanner % (hostname, hostname, hostname)
     VirtualDevice.__init__(self,
                            hostname,
                            echo=echo,
                            login_type=login_type,
                            strict=strict,
                            banner=banner or thebanner)
     self.user_prompt = 'Username: '******'Password: '******'#'
     for command, handler in commands:
         self.add_command(command, handler)
Exemple #5
0
 def __init__(self,
              hostname,
              echo       = True,
              login_type = VirtualDevice.LOGIN_TYPE_BOTH,
              strict     = True,
              banner     = None):
     thebanner = iosbanner % (hostname, hostname, hostname)
     VirtualDevice.__init__(self,
                            hostname,
                            echo       = echo,
                            login_type = login_type,
                            strict     = strict,
                            banner     = banner or thebanner)
     self.user_prompt     = 'Username: '******'Password: '******'#'
     for command, handler in commands:
         self.add_command(command, handler)
Exemple #6
0
 def createVirtualDevice(self):
     self.banner = 'Welcome to %s!\n' % self.hostname
     self.prompt = self.hostname + '> '
     self.device = VirtualDevice(self.hostname, echo = True)
     ls_response = '-rw-r--r--  1 sab  nmc    1628 Aug 18 10:02 file'
     self.device.add_command('ls',   ls_response)
     self.device.add_command('df',   'foobar')
     self.device.add_command('exit', '')
     self.device.add_command('this-command-causes-an-error',
                             '\ncommand not found')
Exemple #7
0
    def __init__(self, device = None, **kwargs):
        """
        @note: Also supports all keyword arguments that L{Protocol} supports.

        @keyword device: The L{Exscript.emulators.VirtualDevice} with
            which to communicate.
        """
        Protocol.__init__(self, **kwargs)
        self.device    = device
        self.init_done = False
        self.cancel    = False
        self.response  = None
        if not self.device:
            self.device = VirtualDevice('dummy', strict = False)
Exemple #8
0
class ProtocolTest(unittest.TestCase):
    """
    Since protocols.Protocol is abstract, this test is only a base class
    for other protocols. It does not do anything fancy on its own.
    """
    CORRELATE = Protocol

    def setUp(self):
        self.hostname = '127.0.0.1'
        self.port = 1236
        self.user = '******'
        self.password = '******'
        self.account = Account(self.user, password=self.password)
        self.daemon = None

        self.createVirtualDevice()
        self.createDaemon()
        if self.daemon is not None:
            self.daemon.start()
            time.sleep(.2)
        self.createProtocol()

    def tearDown(self):
        if self.protocol.__class__ != Protocol:
            self.protocol.close(True)
        if self.daemon is not None:
            self.daemon.exit()
            self.daemon.join()

    def createVirtualDevice(self):
        self.banner = 'Welcome to %s!\n' % self.hostname
        self.prompt = self.hostname + '> '
        self.device = VirtualDevice(self.hostname, echo=True)
        ls_response = '-rw-r--r--  1 sab  nmc    1628 Aug 18 10:02 file'
        self.device.add_command('ls', ls_response)
        self.device.add_command('df', 'foobar')
        self.device.add_command('exit', '')
        self.device.add_command('this-command-causes-an-error',
                                '\ncommand not found')

    def createDaemon(self):
        pass

    def createProtocol(self):
        self.protocol = Protocol(timeout=1)

    def doConnect(self):
        self.protocol.connect(self.hostname, self.port)

    def doLogin(self, flush=True):
        self.doConnect()
        self.protocol.login(self.account, flush=flush)

    def doProtocolAuthenticate(self, flush=True):
        self.doConnect()
        self.protocol.protocol_authenticate(self.account)

    def doAppAuthenticate(self, flush=True):
        self.protocol.app_authenticate(self.account, flush)

    def doAppAuthorize(self, flush=True):
        self.protocol.app_authorize(self.account, flush)

    def _trymatch(self, prompts, string):
        for regex in prompts:
            match = regex.search(string)
            if match:
                return match
        return None

    def testPrompts(self):
        prompts = ('[sam123@home ~]$', '[MyHost-A1]', '<MyHost-A1>',
                   'sam@knip:~/Code/exscript$', 'sam@MyHost-X123>',
                   'sam@MyHost-X123#', 'MyHost-ABC-CDE123>', 'MyHost-A1#',
                   'S-ABC#', '0123456-1-1-abc#', '0123456-1-1-a>',
                   'MyHost-A1(config)#', 'MyHost-A1(config)>',
                   'RP/0/RP0/CPU0:A-BC2#', 'FA/0/1/2/3>',
                   'FA/0/1/2/3(config)>', 'FA/0/1/2/3(config)#',
                   'ec-c3-c27s99(su)->', 'foobar:0>',
                   '[email protected]:/# ',
                   '[email protected]:/% ')
        notprompts = ('one two', ' [MyHost-A1]', '[edit]\r', '[edit]\n',
                      '[edit foo]\r', '[edit foo]\n', '[edit foo]\r\n',
                      '[edit one two]')
        prompt_re = self.protocol.get_prompt()
        for prompt in prompts:
            if not self._trymatch(prompt_re, '\n' + prompt):
                self.fail('Prompt %s does not match exactly.' % prompt)
            if not self._trymatch(prompt_re, 'this is a test\r\n' + prompt):
                self.fail('Prompt %s does not match.' % prompt)
            if self._trymatch(prompt_re, 'some text ' + prompt):
                self.fail('Prompt %s matches incorrectly.' % repr(prompt))
        for prompt in notprompts:
            if self._trymatch(prompt_re, prompt):
                self.fail('Prompt %s matches incorrecly.' % repr(prompt))
            if self._trymatch(prompt_re, prompt + ' '):
                self.fail('Prompt %s matches incorrecly.' % repr(prompt))
            if self._trymatch(prompt_re, '\n' + prompt):
                self.fail('Prompt %s matches incorrecly.' % repr(prompt))

    def testConstructor(self):
        self.assertIsInstance(self.protocol, Protocol)

    def testCopy(self):
        self.assertEqual(self.protocol, self.protocol.__copy__())

    def testDeepcopy(self):
        self.assertEqual(self.protocol, self.protocol.__deepcopy__({}))

    def testIsDummy(self):
        self.assertEqual(self.protocol.is_dummy(), False)

    def testSetDriver(self):
        self.assertTrue(self.protocol.get_driver() is not None)
        self.assertEqual(self.protocol.get_driver().name, 'generic')

        self.protocol.set_driver()
        self.assertTrue(self.protocol.get_driver() is not None)
        self.assertEqual(self.protocol.get_driver().name, 'generic')

        self.protocol.set_driver('ios')
        self.assertTrue(self.protocol.get_driver() is not None)
        self.assertEqual(self.protocol.get_driver().name, 'ios')

        self.protocol.set_driver()
        self.assertTrue(self.protocol.get_driver() is not None)
        self.assertEqual(self.protocol.get_driver().name, 'generic')

    def testGetDriver(self):
        pass  # Already tested in testSetDriver()

    def testAutoinit(self):
        self.protocol.autoinit()

    def _test_prompt_setter(self, getter, setter):
        initial_regex = getter()
        self.assertIsInstance(initial_regex, list)
        self.assertTrue(hasattr(initial_regex[0], 'groups'))

        my_re = re.compile(r'% username')
        setter(my_re)
        regex = getter()
        self.assertIsInstance(regex, list)
        self.assertTrue(hasattr(regex[0], 'groups'))
        self.assertEqual(regex[0], my_re)

        setter()
        regex = getter()
        self.assertEqual(regex, initial_regex)

    def testSetUsernamePrompt(self):
        self._test_prompt_setter(self.protocol.get_username_prompt,
                                 self.protocol.set_username_prompt)

    def testGetUsernamePrompt(self):
        pass  # Already tested in testSetUsernamePrompt()

    def testSetPasswordPrompt(self):
        self._test_prompt_setter(self.protocol.get_password_prompt,
                                 self.protocol.set_password_prompt)

    def testGetPasswordPrompt(self):
        pass  # Already tested in testSetPasswordPrompt()

    def testSetPrompt(self):
        self._test_prompt_setter(self.protocol.get_prompt,
                                 self.protocol.set_prompt)

    def testGetPrompt(self):
        pass  # Already tested in testSetPrompt()

    def testSetErrorPrompt(self):
        self._test_prompt_setter(self.protocol.get_error_prompt,
                                 self.protocol.set_error_prompt)

    def testGetErrorPrompt(self):
        pass  # Already tested in testSetErrorPrompt()

    def testSetLoginErrorPrompt(self):
        self._test_prompt_setter(self.protocol.get_login_error_prompt,
                                 self.protocol.set_login_error_prompt)

    def testGetLoginErrorPrompt(self):
        pass  # Already tested in testSetLoginErrorPrompt()

    def testSetConnectTimeout(self):
        self.assertEqual(self.protocol.get_connect_timeout(), 30)
        self.protocol.set_connect_timeout(60)
        self.assertEqual(self.protocol.get_connect_timeout(), 60)

    def testGetConnectTimeout(self):
        pass  # Already tested in testSetConnectTimeout()

    def testSetTimeout(self):
        self.assertEqual(self.protocol.get_timeout(), 1)
        self.protocol.set_timeout(60)
        self.assertEqual(self.protocol.get_timeout(), 60)

    def testGetTimeout(self):
        pass  # Already tested in testSetTimeout()

    def testConnect(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.connect)
            return
        self.assertEqual(self.protocol.response, None)
        self.doConnect()
        self.assertEqual(self.protocol.response, None)
        self.assertEqual(self.protocol.get_host(), self.hostname)

    def testLogin(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.login, self.account)
            return
        # Password login.
        self.doLogin(flush=False)
        self.assertTrue(self.protocol.response is not None)
        self.assertTrue(len(self.protocol.response) > 0)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())

        # Key login.
        self.tearDown()
        self.setUp()
        key = PrivateKey.from_file('foo', keytype='rsa')
        account = Account(self.user, self.password, key=key)
        self.doConnect()
        self.assertFalse(self.protocol.is_protocol_authenticated())
        self.assertFalse(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())
        self.protocol.login(account, flush=False)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())

    def testAuthenticate(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.authenticate,
                              self.account)
            return
        self.doConnect()

        # Password login.
        self.assertFalse(self.protocol.is_protocol_authenticated())
        self.assertFalse(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())
        self.protocol.authenticate(self.account, flush=False)
        self.assertTrue(self.protocol.response is not None)
        self.assertTrue(len(self.protocol.response) > 0)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())

        # Key login.
        self.tearDown()
        self.setUp()
        key = PrivateKey.from_file('foo', keytype='rsa')
        account = Account(self.user, self.password, key=key)
        self.doConnect()
        self.assertFalse(self.protocol.is_protocol_authenticated())
        self.assertFalse(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())
        self.protocol.authenticate(account, flush=False)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())

    def testProtocolAuthenticate(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.protocol.protocol_authenticate(self.account)
            return
        # There is no guarantee that the device provided any response
        # during protocol level authentification.
        self.doProtocolAuthenticate(flush=False)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertFalse(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())

    def testIsProtocolAuthenticated(self):
        pass  # See testProtocolAuthenticate()

    def testAppAuthenticate(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.app_authenticate,
                              self.account)
            return
        self.testProtocolAuthenticate()
        self.doAppAuthenticate(flush=False)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())

    def testIsAppAuthenticated(self):
        pass  # See testAppAuthenticate()

    def testAppAuthorize(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.app_authorize)
            return
        self.doProtocolAuthenticate(flush=False)
        self.doAppAuthenticate(flush=False)
        response = self.protocol.response

        # Authorize should see that a prompt is still in the buffer,
        # and do nothing.
        self.doAppAuthorize(flush=False)
        self.assertEqual(self.protocol.response, response)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())

        self.doAppAuthorize(flush=True)
        self.assertEqual(self.protocol.response, response)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())

    def testAppAuthorize2(self):
        # Same test as above, but using flush=True all the way.
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.app_authorize)
            return
        self.doProtocolAuthenticate(flush=True)
        self.doAppAuthenticate(flush=True)
        response = self.protocol.response

        # At this point app_authorize should fail because the buffer is
        # empty due to flush=True above. In other words, app_authorize
        # will wait for a prompt until a timeout happens.
        self.assertRaises(TimeoutException, self.doAppAuthorize)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())

    def testAutoAppAuthorize(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(TypeError, self.protocol.auto_app_authorize)
            return

        self.testAppAuthenticate()
        response = self.protocol.response

        # This should do nothing, because our test host does not
        # support AAA. Can't think of a way to test against a
        # device using AAA.
        self.protocol.auto_app_authorize(self.account, flush=False)
        self.assertEqual(self.protocol.response, response)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())

        self.protocol.auto_app_authorize(self.account, flush=True)
        self.assertEqual(self.protocol.response, response)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())

    def testIsAppAuthorized(self):
        pass  # see testAppAuthorize()

    def testSend(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.send, 'ls')
            return
        self.doLogin()
        self.protocol.execute('ls')

        self.protocol.send('df\r')
        self.assertTrue(self.protocol.response is not None)
        self.assertTrue(self.protocol.response.startswith('ls'))

        self.protocol.send('exit\r')
        self.assertTrue(self.protocol.response is not None)
        self.assertTrue(self.protocol.response.startswith('ls'))

    def testExecute(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.execute, 'ls')
            return
        self.doLogin()
        self.protocol.execute('ls')
        self.assertTrue(self.protocol.response is not None)
        self.assertTrue(self.protocol.response.startswith('ls'))

        # Make sure that we raise an error if the device responds
        # with something that matches any of the error prompts.
        self.protocol.set_error_prompt('.')
        self.assertRaises(InvalidCommandException, self.protocol.execute,
                          'this-command-causes-an-error')

    def testWaitfor(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.waitfor, 'ls')
            return
        self.doLogin()
        oldresponse = self.protocol.response
        self.protocol.send('ls\r')
        self.assertEqual(oldresponse, self.protocol.response)
        self.protocol.waitfor(re.compile(r'[\r\n]'))
        self.assertNotEqual(oldresponse, self.protocol.response)
        oldresponse = self.protocol.response
        self.protocol.waitfor(re.compile(r'[\r\n]'))
        self.assertEqual(oldresponse, self.protocol.response)

    def testExpect(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.expect, 'ls')
            return
        self.doLogin()
        oldresponse = self.protocol.response
        self.protocol.send('ls\r')
        self.assertEqual(oldresponse, self.protocol.response)
        self.protocol.expect(re.compile(r'[\r\n]'))
        self.assertNotEqual(oldresponse, self.protocol.response)

    def testExpectPrompt(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.expect, 'ls')
            return
        self.doLogin()
        oldresponse = self.protocol.response
        self.protocol.send('ls\r')
        self.assertEqual(oldresponse, self.protocol.response)
        self.protocol.expect_prompt()
        self.assertNotEqual(oldresponse, self.protocol.response)

    def testAddMonitor(self):
        # Set the monitor callback up.
        def monitor_cb(thedata, *args, **kwargs):
            thedata['args'] = args
            thedata['kwargs'] = kwargs

        data = {}
        self.protocol.add_monitor('abc', partial(monitor_cb, data))

        # Simulate some non-matching data.
        self.protocol.buffer.append(u'aaa')
        self.assertEqual(data, {})

        # Simulate some matching data.
        self.protocol.buffer.append(u'abc')
        self.assertEqual(len(data.get('args')), 3)
        self.assertEqual(data.get('args')[0], self.protocol)
        self.assertEqual(data.get('args')[1], 0)
        self.assertEqual(data.get('args')[2].group(0), 'abc')
        self.assertEqual(data.get('kwargs'), {})

    def testGetBuffer(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            return
        self.assertEqual(str(self.protocol.buffer), '')
        self.doLogin()
        # Depending on whether the connected host sends a banner,
        # the buffer may or may not contain anything now.

        before = str(self.protocol.buffer)
        self.protocol.send('ls\r')
        self.protocol.waitfor(self.protocol.get_prompt())
        self.assertNotEqual(str(self.protocol.buffer), before)

    def _cancel_cb(self, data):
        self.protocol.cancel_expect()

    def testCancelExpect(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            return
        self.doLogin()
        oldresponse = self.protocol.response
        self.protocol.data_received_event.connect(self._cancel_cb)
        self.protocol.send('ls\r')
        self.assertEqual(oldresponse, self.protocol.response)
        self.assertRaises(ExpectCancelledException, self.protocol.expect,
                          'notgoingtohappen')

    def testInteract(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.interact)
            return
        # Can't really be tested.

    def testClose(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.close)
            return
        self.doConnect()
        self.protocol.close(True)

    def testGetHost(self):
        self.assertTrue(self.protocol.get_host() is None)
        if self.protocol.__class__ == Protocol:
            return
        self.doConnect()
        self.assertEqual(self.protocol.get_host(), self.hostname)

    def testGuessOs(self):
        self.assertEqual('unknown', self.protocol.guess_os())
        # Other tests can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.close)
            return
        self.doConnect()
        self.assertEqual('unknown', self.protocol.guess_os())
        self.protocol.login(self.account)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())
        self.assertEqual('shell', self.protocol.guess_os())
Exemple #9
0
class Dummy(Protocol):
    """
    This protocol adapter does not open a network connection, but talks to
    a L{Exscript.emulators.VirtualDevice} internally.
    """
    def __init__(self, device=None, **kwargs):
        """
        @note: Also supports all keyword arguments that L{Protocol} supports.

        @keyword device: The L{Exscript.emulators.VirtualDevice} with
            which to communicate.
        """
        Protocol.__init__(self, **kwargs)
        self.device = device
        self.init_done = False
        self.cancel = False
        self.response = None
        if not self.device:
            self.device = VirtualDevice('dummy', strict=False)

    def is_dummy(self):
        return True

    def _expect_any(self, prompt_list, flush=True):
        self._doinit()

        # Cancelled by a callback during self._say().
        if self.cancel:
            self.cancel = False
            return -2, None, self.response

        # Look for a match in the buffer.
        for i, prompt in enumerate(prompt_list):
            matches = prompt.search(str(self.buffer))
            if matches is not None:
                self.response = self.buffer.head(matches.start())
                if flush:
                    self.buffer.pop(matches.end())
                return i, matches, self.response

        # "Timeout".
        return -1, None, self.response

    def _say(self, string):
        self._receive_cb(string)
        self.buffer.append(string)

    def cancel_expect(self):
        self.cancel = True

    def _connect_hook(self, hostname, port):
        # To more correctly mimic the behavior of a network device, we
        # do not send the banner here, but in authenticate() instead.
        self.buffer.clear()
        return True

    def _doinit(self):
        if not self.init_done:
            self.init_done = True
            self._say(self.device.init())

    def _protocol_authenticate(self, user, password):
        self._doinit()

    def _protocol_authenticate_by_key(self, user, key):
        self._doinit()

    def send(self, data):
        self._dbg(4, 'Sending %s' % repr(data))
        self._say(self.device.do(data))

    def _domatch(self, prompt, flush):
        # Wait for a prompt.
        result, match, self.response = self._expect_any(prompt, flush)

        if match:
            self._dbg(2, "Got a prompt, match was %s" % repr(match.group()))
        else:
            self._dbg(2, "No prompt match")

        self._dbg(5, "Response was %s" % repr(str(self.buffer)))

        if result == -1:
            error = 'Error while waiting for response from device'
            raise TimeoutException(error)
        if result == -2:
            if self.driver_replaced:
                self.driver_replaced = False
                raise DriverReplacedException()
            else:
                raise ExpectCancelledException()

        return result, match

    def close(self, force=False):
        self._say('\n')
        self.buffer.clear()
Exemple #10
0
class ServerTest(unittest.TestCase):
    CORRELATE = Server.Server

    def setUp(self):
        self.host   = 'localhost'
        self.port   = 1235
        self.device = VirtualDevice(self.host, echo = False)
        self.daemon = Server.Server(self.host, self.port, self.device)
        self.device.set_prompt(self.host + ':' + str(self.port) + '> ')

    def tearDown(self):
        if self.daemon:
            self.daemon.exit()
        if self.daemon.__class__ != Server.Server:
            self.daemon.join()

    def _create_daemon(self):
        raise NotImplementedError()

    def _create_client(self):
        raise NotImplementedError()

    def _add_commands(self):
        self.device.add_command('exit', self.daemon.exit_command)
        self.device.add_command('ls',   'ok1')
        self.device.add_command('ll',   'ok2\nfoobar:1>', prompt = False)
        self.device.add_command('.+',   'Unknown command.')

    def testConstructor(self):
        # Test can not work on the abstract base.
        if self.daemon.__class__ == Server.Server:
            return
        self._create_daemon()
        self.daemon.start()
        time.sleep(1)

    def testStart(self):
        # Test can not work on the abstract base.
        if self.daemon.__class__ == Server.Server:
            return
        self._create_daemon()
        self._add_commands()
        self.daemon.start()
        time.sleep(1)

        client = self._create_client()
        client.set_prompt(re.compile(r'\w+:\d+> ?'))
        client.connect(self.host, self.port)
        client.login(Account('user', 'password'))
        client.execute('ls')
        self.assertEqual(client.response, 'ok1\n')
        client.execute('ll')
        self.assertEqual(client.response, 'ok2\n')
        client.send('exit\r')

    def testExitCommand(self):
        pass # tested in testExit()

    def testExit(self):
        # Test can not work on the abstract base.
        if self.daemon.__class__ == Server.Server:
            return
        self.testStart()
        # Since testStart() sent an "exit" command to the server,
        # it should be shutting down even without us calling
        # self.daemon.exit().
        self.daemon.join()
        self.testConstructor()
Exemple #11
0
 def setUp(self):
     self.host   = 'localhost'
     self.port   = 1235
     self.device = VirtualDevice(self.host, echo = False)
     self.daemon = Server.Server(self.host, self.port, self.device)
     self.device.set_prompt(self.host + ':' + str(self.port) + '> ')
Exemple #12
0
 def setUp(self):
     self.host = 'localhost'
     self.port = 1235
     self.device = VirtualDevice(self.host, echo=False)
     self.daemon = Server(self.host, self.port, self.device)
     self.device.set_prompt(self.host + ':' + str(self.port) + '> ')
Exemple #13
0
class ServerTest(unittest.TestCase):
    CORRELATE = Server

    def setUp(self):
        self.host = 'localhost'
        self.port = 1235
        self.device = VirtualDevice(self.host, echo=False)
        self.daemon = Server(self.host, self.port, self.device)
        self.device.set_prompt(self.host + ':' + str(self.port) + '> ')

    def tearDown(self):
        if self.daemon:
            self.daemon.exit()
        if self.daemon.__class__ != Server:
            self.daemon.join()

    def _create_daemon(self):
        raise NotImplementedError()

    def _create_client(self):
        raise NotImplementedError()

    def _add_commands(self):
        self.device.add_command('exit', self.daemon.exit_command)
        self.device.add_command('ls', 'ok1')
        self.device.add_command('ll', 'ok2\nfoobar:1>', prompt=False)
        self.device.add_command('.+', 'Unknown command.')

    def testConstructor(self):
        # Test can not work on the abstract base.
        if self.daemon.__class__ == Server:
            return
        self._create_daemon()
        self.daemon.start()
        time.sleep(1)

    def testStart(self):
        # Test can not work on the abstract base.
        if self.daemon.__class__ == Server:
            return
        self._create_daemon()
        self._add_commands()
        self.daemon.start()
        time.sleep(1)

        client = self._create_client()
        client.set_prompt(re.compile(r'\w+:\d+> ?'))
        client.connect(self.host, self.port)
        client.login(Account('user', 'password'))
        client.execute('ls')
        self.assertEqual(client.response, 'ok1\n')
        client.execute('ll')
        self.assertEqual(client.response, 'ok2\n')
        client.send('exit\r')

    def testExitCommand(self):
        pass  # tested in testExit()

    def testExit(self):
        # Test can not work on the abstract base.
        if self.daemon.__class__ == Server:
            return
        self.testStart()
        # Since testStart() sent an "exit" command to the server,
        # it should be shutting down even without us calling
        # self.daemon.exit().
        self.daemon.join()
        self.testConstructor()
Exemple #14
0
class ProtocolTest(unittest.TestCase):
    """
    Since protocols.Protocol is abstract, this test is only a base class
    for other protocols. It does not do anything fancy on its own.
    """
    CORRELATE = Protocol

    def setUp(self):
        self.hostname = '127.0.0.1'
        self.port     = 1236
        self.user     = '******'
        self.password = '******'
        self.account  = Account(self.user, password = self.password)
        self.daemon   = None

        self.createVirtualDevice()
        self.createDaemon()
        if self.daemon is not None:
            self.daemon.start()
            time.sleep(.2)
        self.createProtocol()

    def tearDown(self):
        if self.daemon is not None:
            self.daemon.exit()
            self.daemon.join()

    def createVirtualDevice(self):
        self.banner = 'Welcome to %s!\n' % self.hostname
        self.prompt = self.hostname + '> '
        self.device = VirtualDevice(self.hostname, echo = True)
        ls_response = '-rw-r--r--  1 sab  nmc    1628 Aug 18 10:02 file'
        self.device.add_command('ls',   ls_response)
        self.device.add_command('df',   'foobar')
        self.device.add_command('exit', '')
        self.device.add_command('this-command-causes-an-error',
                                '\ncommand not found')

    def createDaemon(self):
        pass

    def createProtocol(self):
        self.protocol = Protocol()

    def doConnect(self):
        self.protocol.connect(self.hostname, self.port)

    def doLogin(self, flush = True):
        self.doConnect()
        self.protocol.login(self.account, flush = flush)

    def doProtocolAuthenticate(self, flush = True):
        self.doConnect()
        self.protocol.protocol_authenticate(self.account)

    def doAppAuthenticate(self, flush = True):
        self.protocol.app_authenticate(self.account, flush)

    def doAppAuthorize(self, flush = True):
        self.protocol.app_authorize(self.account, flush)

    def _trymatch(self, prompts, string):
        for regex in prompts:
            match = regex.search(string)
            if match:
                return match
        return None

    def testPrompts(self):
        prompts = ('[sam123@home ~]$',
                   '[MyHost-A1]',
                   '<MyHost-A1>',
                   'sam@knip:~/Code/exscript$',
                   'sam@MyHost-X123>',
                   'sam@MyHost-X123#',
                   'MyHost-ABC-CDE123>',
                   'MyHost-A1#',
                   'S-ABC#',
                   '0123456-1-1-abc#',
                   '0123456-1-1-a>',
                   'MyHost-A1(config)#',
                   'MyHost-A1(config)>',
                   'RP/0/RP0/CPU0:A-BC2#',
                   'FA/0/1/2/3>',
                   'FA/0/1/2/3(config)>',
                   'FA/0/1/2/3(config)#',
                   'ec-c3-c27s99(su)->',
                   'foobar:0>',
                   '[email protected]:/# ',
                   '[email protected]:/% ')
        notprompts = ('one two',
                      ' [MyHost-A1]',
                      '[edit]\r',
                      '[edit]\n',
                      '[edit foo]\r',
                      '[edit foo]\n',
                      '[edit foo]\r\n',
                      '[edit one two]')
        prompt_re = self.protocol.get_prompt()
        for prompt in prompts:
            if not self._trymatch(prompt_re, '\n' + prompt):
                self.fail('Prompt %s does not match exactly.' % prompt)
            if not self._trymatch(prompt_re, 'this is a test\r\n' + prompt):
                self.fail('Prompt %s does not match.' % prompt)
            if self._trymatch(prompt_re, 'some text ' + prompt):
                self.fail('Prompt %s matches incorrectly.' % repr(prompt))
        for prompt in notprompts:
            if self._trymatch(prompt_re, prompt):
                self.fail('Prompt %s matches incorrecly.' % repr(prompt))
            if self._trymatch(prompt_re, prompt + ' '):
                self.fail('Prompt %s matches incorrecly.' % repr(prompt))
            if self._trymatch(prompt_re, '\n' + prompt):
                self.fail('Prompt %s matches incorrecly.' % repr(prompt))

    def testConstructor(self):
        self.assertTrue(isinstance(self.protocol, Protocol))

    def testCopy(self):
        self.assertEqual(self.protocol, self.protocol.__copy__())

    def testDeepcopy(self):
        self.assertEqual(self.protocol, self.protocol.__deepcopy__({}))

    def testIsDummy(self):
        self.assertEqual(self.protocol.is_dummy(), False)

    def testSetDriver(self):
        self.assertTrue(self.protocol.get_driver() is not None)
        self.assertEqual(self.protocol.get_driver().name, 'generic')

        self.protocol.set_driver()
        self.assertTrue(self.protocol.get_driver() is not None)
        self.assertEqual(self.protocol.get_driver().name, 'generic')

        self.protocol.set_driver('ios')
        self.assertTrue(self.protocol.get_driver() is not None)
        self.assertEqual(self.protocol.get_driver().name, 'ios')

        self.protocol.set_driver()
        self.assertTrue(self.protocol.get_driver() is not None)
        self.assertEqual(self.protocol.get_driver().name, 'generic')

    def testGetDriver(self):
        pass # Already tested in testSetDriver()

    def testAutoinit(self):
        self.protocol.autoinit()

    def _test_prompt_setter(self, getter, setter):
        initial_regex = getter()
        self.assertTrue(isinstance(initial_regex, list))
        self.assertTrue(hasattr(initial_regex[0], 'groups'))

        my_re = re.compile(r'% username')
        setter(my_re)
        regex = getter()
        self.assertTrue(isinstance(regex, list))
        self.assertTrue(hasattr(regex[0], 'groups'))
        self.assertEqual(regex[0], my_re)

        setter()
        regex = getter()
        self.assertEqual(regex, initial_regex)

    def testSetUsernamePrompt(self):
        self._test_prompt_setter(self.protocol.get_username_prompt,
                                 self.protocol.set_username_prompt)

    def testGetUsernamePrompt(self):
        pass # Already tested in testSetUsernamePrompt()

    def testSetPasswordPrompt(self):
        self._test_prompt_setter(self.protocol.get_password_prompt,
                                 self.protocol.set_password_prompt)

    def testGetPasswordPrompt(self):
        pass # Already tested in testSetPasswordPrompt()

    def testSetPrompt(self):
        self._test_prompt_setter(self.protocol.get_prompt,
                                 self.protocol.set_prompt)

    def testGetPrompt(self):
        pass # Already tested in testSetPrompt()

    def testSetErrorPrompt(self):
        self._test_prompt_setter(self.protocol.get_error_prompt,
                                 self.protocol.set_error_prompt)

    def testGetErrorPrompt(self):
        pass # Already tested in testSetErrorPrompt()

    def testSetLoginErrorPrompt(self):
        self._test_prompt_setter(self.protocol.get_login_error_prompt,
                                 self.protocol.set_login_error_prompt)

    def testGetLoginErrorPrompt(self):
        pass # Already tested in testSetLoginErrorPrompt()

    def testSetConnectTimeout(self):
        self.assertTrue(self.protocol.get_connect_timeout() == 30)
        self.protocol.set_connect_timeout(60)
        self.assertTrue(self.protocol.get_connect_timeout() == 60)

    def testGetConnectTimeout(self):
        pass # Already tested in testSetConnectTimeout()

    def testSetTimeout(self):
        self.assertTrue(self.protocol.get_timeout() == 30)
        self.protocol.set_timeout(60)
        self.assertTrue(self.protocol.get_timeout() == 60)

    def testGetTimeout(self):
        pass # Already tested in testSetTimeout()

    def testConnect(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.connect)
            return
        self.assertEqual(self.protocol.response, None)
        self.doConnect()
        self.assertEqual(self.protocol.response, None)
        self.assertEqual(self.protocol.get_host(), self.hostname)

    def testLogin(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception,
                              self.protocol.login,
                              self.account)
            return
        # Password login.
        self.doLogin(flush = False)
        self.assertTrue(self.protocol.response is not None)
        self.assertTrue(len(self.protocol.response) > 0)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())

        # Key login.
        self.tearDown()
        self.setUp()
        key     = PrivateKey.from_file('foo', keytype = 'rsa')
        account = Account(self.user, self.password, key = key)
        self.doConnect()
        self.assertFalse(self.protocol.is_protocol_authenticated())
        self.assertFalse(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())
        self.protocol.login(account, flush = False)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())

    def testAuthenticate(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception,
                              self.protocol.authenticate,
                              self.account)
            return
        self.doConnect()

        # Password login.
        self.assertFalse(self.protocol.is_protocol_authenticated())
        self.assertFalse(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())
        self.protocol.authenticate(self.account, flush = False)
        self.assertTrue(self.protocol.response is not None)
        self.assertTrue(len(self.protocol.response) > 0)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())

        # Key login.
        self.tearDown()
        self.setUp()
        key     = PrivateKey.from_file('foo', keytype = 'rsa')
        account = Account(self.user, self.password, key = key)
        self.doConnect()
        self.assertFalse(self.protocol.is_protocol_authenticated())
        self.assertFalse(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())
        self.protocol.authenticate(account, flush = False)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())

    def testProtocolAuthenticate(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.protocol.protocol_authenticate(self.account)
            return
        # There is no guarantee that the device provided any response
        # during protocol level authentification.
        self.doProtocolAuthenticate(flush = False)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertFalse(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())

    def testIsProtocolAuthenticated(self):
        pass # See testProtocolAuthenticate()

    def testAppAuthenticate(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception,
                              self.protocol.app_authenticate,
                              self.account)
            return
        self.testProtocolAuthenticate()
        self.doAppAuthenticate(flush = False)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertFalse(self.protocol.is_app_authorized())

    def testIsAppAuthenticated(self):
        pass # See testAppAuthenticate()

    def testAppAuthorize(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.app_authorize)
            return
        self.doProtocolAuthenticate(flush = False)
        self.doAppAuthenticate(flush = False)
        response = self.protocol.response

        # Authorize should see that a prompt is still in the buffer,
        # and do nothing.
        self.doAppAuthorize(flush = False)
        self.assertEqual(self.protocol.response, response)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())

        self.doAppAuthorize(flush = True)
        self.assertEqual(self.protocol.response, response)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())

    def testAutoAppAuthorize(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(TypeError, self.protocol.auto_app_authorize)
            return

        self.testAppAuthenticate()
        response = self.protocol.response

        # This should do nothing, because our test host does not
        # support AAA. Can't think of a way to test against a
        # device using AAA.
        self.protocol.auto_app_authorize(self.account, flush = False)
        self.assertEqual(self.protocol.response, response)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())

        self.protocol.auto_app_authorize(self.account, flush = True)
        self.assertEqual(self.protocol.response, response)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())

    def testIsAppAuthorized(self):
        pass # see testAppAuthorize()

    def testSend(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.send, 'ls')
            return
        self.doLogin()
        self.protocol.execute('ls')

        self.protocol.send('df\r')
        self.assertTrue(self.protocol.response is not None)
        self.assertTrue(self.protocol.response.startswith('ls'))

        self.protocol.send('exit\r')
        self.assertTrue(self.protocol.response is not None)
        self.assertTrue(self.protocol.response.startswith('ls'))

    def testExecute(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.execute, 'ls')
            return
        self.doLogin()
        self.protocol.execute('ls')
        self.assertTrue(self.protocol.response is not None)
        self.assertTrue(self.protocol.response.startswith('ls'))

        # Make sure that we raise an error if the device responds
        # with something that matches any of the error prompts.
        self.protocol.set_error_prompt('.')
        self.assertRaises(InvalidCommandException,
                          self.protocol.execute,
                          'this-command-causes-an-error')

    def testWaitfor(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.waitfor, 'ls')
            return
        self.doLogin()
        oldresponse = self.protocol.response
        self.protocol.send('ls\r')
        self.assertEqual(oldresponse, self.protocol.response)
        self.protocol.waitfor(re.compile(r'[\r\n]'))
        self.assertNotEqual(oldresponse, self.protocol.response)
        oldresponse = self.protocol.response
        self.protocol.waitfor(re.compile(r'[\r\n]'))
        self.assertEqual(oldresponse, self.protocol.response)

    def testExpect(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.expect, 'ls')
            return
        self.doLogin()
        oldresponse = self.protocol.response
        self.protocol.send('ls\r')
        self.assertEqual(oldresponse, self.protocol.response)
        self.protocol.expect(re.compile(r'[\r\n]'))
        self.assertNotEqual(oldresponse, self.protocol.response)

    def testExpectPrompt(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.expect, 'ls')
            return
        self.doLogin()
        oldresponse = self.protocol.response
        self.protocol.send('ls\r')
        self.assertEqual(oldresponse, self.protocol.response)
        self.protocol.expect_prompt()
        self.assertNotEqual(oldresponse, self.protocol.response)

    def testAddMonitor(self):
        # Set the monitor callback up.
        def monitor_cb(thedata, *args, **kwargs):
            thedata['args']   = args
            thedata['kwargs'] = kwargs
        data = {}
        self.protocol.add_monitor('abc', partial(monitor_cb, data))

        # Simulate some non-matching data.
        self.protocol.buffer.append('aaa')
        self.assertEqual(data, {})

        # Simulate some matching data.
        self.protocol.buffer.append('abc')
        self.assertEqual(len(data.get('args')), 3)
        self.assertEqual(data.get('args')[0], self.protocol)
        self.assertEqual(data.get('args')[1], 0)
        self.assertEqual(data.get('args')[2].group(0), 'abc')
        self.assertEqual(data.get('kwargs'), {})

    def testGetBuffer(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            return
        self.assertEqual(str(self.protocol.buffer), '')
        self.doLogin()
        # Depending on whether the connected host sends a banner,
        # the buffer may or may not contain anything now.

        before = str(self.protocol.buffer)
        self.protocol.send('ls\r')
        self.protocol.waitfor(self.protocol.get_prompt())
        self.assertNotEqual(str(self.protocol.buffer), before)

    def _cancel_cb(self, data):
        self.protocol.cancel_expect()

    def testCancelExpect(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            return
        self.doLogin()
        oldresponse = self.protocol.response
        self.protocol.data_received_event.connect(self._cancel_cb)
        self.protocol.send('ls\r')
        self.assertEqual(oldresponse, self.protocol.response)
        self.assertRaises(ExpectCancelledException,
                          self.protocol.expect,
                          'notgoingtohappen')

    def testInteract(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.interact)
            return
        # Can't really be tested.

    def testClose(self):
        # Test can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.close)
            return
        self.doConnect()
        self.protocol.close(True)

    def testGetHost(self):
        self.assertTrue(self.protocol.get_host() is None)
        if self.protocol.__class__ == Protocol:
            return
        self.doConnect()
        self.assertEqual(self.protocol.get_host(), self.hostname)

    def testGuessOs(self):
        self.assertEqual('unknown', self.protocol.guess_os())
        # Other tests can not work on the abstract base.
        if self.protocol.__class__ == Protocol:
            self.assertRaises(Exception, self.protocol.close)
            return
        self.doConnect()
        self.assertEqual('unknown', self.protocol.guess_os())
        self.protocol.login(self.account)
        self.assertTrue(self.protocol.is_protocol_authenticated())
        self.assertTrue(self.protocol.is_app_authenticated())
        self.assertTrue(self.protocol.is_app_authorized())
        self.assertEqual('shell', self.protocol.guess_os())
Exemple #15
0
    def testDummy(self):
        # Test simple instance with banner.
        protocol = Dummy(device = self.device)
        protocol.connect('testhost')
        self.assertEqual(str(protocol.buffer), '')
        self.assertEqual(protocol.response, None)
        protocol.close()

        # Test login.
        protocol = Dummy(device = self.device)
        protocol.connect('testhost')
        self.assertEqual(str(protocol.buffer), '')
        self.assertEqual(protocol.response, None)
        protocol.login(self.account, flush = False)
        self.assertEqual(protocol.buffer.tail(len(self.prompt)), self.prompt)
        protocol.close()

        # Test login with user prompt.
        device = VirtualDevice(self.hostname,
                               echo       = True,
                               login_type = VirtualDevice.LOGIN_TYPE_USERONLY)
        protocol = self._create_dummy_and_eat_banner(device)
        self.assertEqual(str(protocol.buffer), 'User: '******'Password: '******'User: '******'')
        self.assertEqual(protocol.response, self.user + '\r')
        protocol.close()

        # Test login with password prompt and wait parameter.
        device = VirtualDevice(self.hostname,
                               echo       = True,
                               login_type = VirtualDevice.LOGIN_TYPE_PASSWORDONLY)
        protocol = self._create_dummy_and_eat_banner(device)
        self.assertEqual(str(protocol.buffer), 'Password: '******'')
        self.assertEqual(protocol.response, self.password + '\r')
        protocol.close()

        # Test login with port number.
        protocol = self._create_dummy_and_eat_banner(device, 1234)
        self.assertEqual(str(protocol.buffer), 'Password: '******'')
        self.assertEqual(protocol.response, self.password + '\r')
        protocol.close()

        # Test a custom response.
        device = VirtualDevice(self.hostname,
                               echo       = True,
                               login_type = VirtualDevice.LOGIN_TYPE_NONE)
        protocol = Dummy(device = device)
        command  = re.compile(r'testcommand')
        response = 'hello world\r\n%s> ' % self.hostname
        device.add_command(command, response, prompt = False)
        protocol.set_prompt(re.compile(r'> $'))
        protocol.connect('testhost')
        protocol.expect(re.compile(re.escape(self.banner)))
        self.assertEqual(protocol.response, '')
        self.assertEqual(str(protocol.buffer), self.prompt)
        protocol.expect_prompt()
        self.assertEqual(str(protocol.buffer), '')
        self.assertEqual(protocol.response, self.hostname)
        protocol.execute('testcommand')
        expected = 'testcommand\rhello world\r\n' + self.hostname
        self.assertEqual(protocol.response, expected)
        self.assertEqual(str(protocol.buffer), '')
        protocol.close()
Exemple #16
0
class Dummy(Protocol):
    """
    This protocol adapter does not open a network connection, but talks to
    a L{Exscript.emulators.VirtualDevice} internally.
    """

    def __init__(self, device = None, **kwargs):
        """
        @note: Also supports all keyword arguments that L{Protocol} supports.

        @keyword device: The L{Exscript.emulators.VirtualDevice} with
            which to communicate.
        """
        Protocol.__init__(self, **kwargs)
        self.device    = device
        self.init_done = False
        self.cancel    = False
        self.response  = None
        if not self.device:
            self.device = VirtualDevice('dummy', strict = False)

    def is_dummy(self):
        return True

    def _expect_any(self, prompt_list, flush = True):
        self._doinit()

        # Cancelled by a callback during self._say().
        if self.cancel:
            self.cancel = False
            return -2, None, self.response

        # Look for a match in the buffer.
        for i, prompt in enumerate(prompt_list):
            matches = prompt.search(str(self.buffer))
            if matches is not None:
                self.response = self.buffer.head(matches.start())
                if flush:
                    self.buffer.pop(matches.end())
                return i, matches, self.response

        # "Timeout".
        return -1, None, self.response

    def _say(self, string):
        self._receive_cb(string)
        self.buffer.append(string)

    def cancel_expect(self):
        self.cancel = True

    def _connect_hook(self, hostname, port):
        # To more correctly mimic the behavior of a network device, we
        # do not send the banner here, but in authenticate() instead.
        self.buffer.clear()
        return True

    def _doinit(self):
        if not self.init_done:
            self.init_done = True
            self._say(self.device.init())

    def _protocol_authenticate(self, user, password):
        self._doinit()

    def _protocol_authenticate_by_key(self, user, key):
        self._doinit()

    def send(self, data):
        self._dbg(4, 'Sending %s' % repr(data))
        self._say(self.device.do(data))

    def _domatch(self, prompt, flush):
        # Wait for a prompt.
        result, match, self.response = self._expect_any(prompt, flush)

        if match:
            self._dbg(2, "Got a prompt, match was %s" % repr(match.group()))
        else:
            self._dbg(2, "No prompt match")

        self._dbg(5, "Response was %s" % repr(str(self.buffer)))

        if result == -1:
            error = 'Error while waiting for response from device'
            raise TimeoutException(error)
        if result == -2:
            if self.driver_replaced:
                self.driver_replaced = False
                raise DriverReplacedException()
            else:
                raise ExpectCancelledException()

        return result, match

    def close(self, force = False):
        self._say('\n')
        self.buffer.clear()