def test_close(self, mock_close): device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj._transport = paramiko.Transport(MagicMock()) obj._transport.active = True obj._connected = True obj.close() mock_close.assert_called_once_with() self.assertFalse(obj._connected)
def test_run_recieve(self, mock_error, mock_select, mock_recv, mock_close): mock_select.return_value = True, None, None mock_recv.return_value = 0 device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj._channel = paramiko.Channel("c100") obj.run() self.assertTrue( isinstance(mock_error.call_args_list[0][0][0], SessionCloseError))
def test_dispatch_message(self, mock_handler): cap = [':candidate'] obj = Session(cap) device_handler = JunosDeviceHandler({'name': 'junos'}) obj._device_handler = device_handler listener = HelloHandler(None, None) obj._listeners.add(listener) obj._dispatch_message(rpc_reply) mock_handler.assert_called_once_with(parse_root(rpc_reply), rpc_reply)
def test_auth_agent_exception(self, mock_get_key, mock_auth_public_key): key = paramiko.PKey() mock_get_key.return_value = [key] mock_auth_public_key.side_effect = paramiko.ssh_exception.AuthenticationException device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj._transport = paramiko.Transport(MagicMock()) self.assertRaises(AuthenticationError, obj._auth, 'user', None, [], True, False)
def test_auth_password(self, mock_auth_password): device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj._transport = paramiko.Transport(MagicMock()) obj._auth('user', 'password', [], False, True) self.assertEqual( mock_auth_password.call_args_list[0][0], ('user', 'password'))
def test_auth_agent(self, mock_get_key, mock_auth_public_key): key = paramiko.PKey(msg="hello") mock_get_key.return_value = [key] device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj._transport = paramiko.Transport(MagicMock()) obj._auth('user', 'password', [], True, True) self.assertEqual( (mock_auth_public_key.call_args_list[0][0][1]).__repr__(), key.__repr__())
def test_auth_keyfiles(self, mock_get_key, mock_auth_public_key): key = paramiko.PKey() mock_get_key.return_value = key device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj._transport = paramiko.Transport(MagicMock()) obj._auth('user', 'password', ["key_file_name"], False, True) self.assertEqual( (mock_auth_public_key.call_args_list[0][0][1]).__repr__(), key.__repr__())
def test_auth_default_keyfiles_exception(self, mock_get_key, mock_auth_public_key, mock_is_file): key = paramiko.PKey() mock_is_file.return_value = True mock_get_key.side_effect = paramiko.ssh_exception.PasswordRequiredException device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj._transport = paramiko.Transport(MagicMock()) self.assertRaises(AuthenticationError, obj._auth,'user', None, [], False, True)
def test_ssh_known_hosts(self, mock_auth, mock_pc, mock_transport, mock_hk, mock_os, mock_hex): mock_os.return_value = "file_name" hk_inst = MagicMock(check=MagicMock(return_value=True)) mock_hk.return_value = hk_inst device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj.connect(host='h', sock=MagicMock()) hk_inst.load.assert_called_once_with('file_name') mock_os.assert_called_once_with('~/.ssh/known_hosts')
def test_dispatch_message_error(self, mock_log, mock_parse_root): mock_parse_root.side_effect = Exception cap = [':candidate'] obj = Session(cap) device_handler = JunosDeviceHandler({'name': 'junos'}) obj._device_handler = device_handler listener = HelloHandler(None, None) obj._listeners.add(listener) obj._dispatch_message(rpc_reply) self.assertNotEqual( mock_log.call_args_list[0][0][0].find("error parsing dispatch message"), -1)
def test_run_send(self, mock_error, mock_send, mock_ready, mock_close): mock_ready.return_value = True mock_send.return_value = -1 device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj._channel = paramiko.Channel("c100") obj._q.put("rpc") obj.run() self.assertEqual(mock_send.call_args_list[0][0][0], "rpc") self.assertTrue( isinstance(mock_error.call_args_list[0][0][0], SessionCloseError))
def test_dispatch_msg_err_during_cap_exchange(self, mock_log, mock_parse_root): mock_parse_root.side_effect = Exception logging.basicConfig(level=logging.CRITICAL) cap = [':candidate'] obj = Session(cap) device_handler = JunosDeviceHandler({'name': 'junos'}) obj._device_handler = device_handler listener = HelloHandler(None, None) obj._listeners.add(listener) obj._dispatch_message(cap_excahnge_err_reply) self.assertNotEqual( mock_log.call_args_list[1][0][0].find("dispatching error to"), -1)
def test_ssh_known_hosts_2(self, mock_auth, mock_pc, mock_sshc, mock_transport, mock_hk, mock_os, mock_open, mock_hex): mock_os.return_value = "file_name" hk_inst = MagicMock(check=MagicMock(return_value=True)) mock_hk.return_value = hk_inst config = {'userknownhostsfile': 'known_hosts_file'} mock_sshc.return_value = MagicMock(lookup=lambda _h: config) device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj.connect(host='h', sock=MagicMock(), ssh_config=True) hk_inst.load.assert_called_once_with('file_name') mock_os.mock_calls == [call('~/.ssh/config'), call('known_hosts_file')]
def _test_parsemethod(self, mock_dispatch, parsemethod, reply, ok_chunk): device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) if sys.version >= "3.0": obj._buffer.write(bytes(reply, "utf-8")) remainder = bytes(ok_chunk, "utf-8") else: obj._buffer.write(reply) remainder = ok_chunk parsemethod(obj) call = mock_dispatch.call_args_list[0][0][0] self.assertEqual(call, reply_data) self.assertEqual(obj._buffer.getvalue(), remainder)
def setUp(self, mock_connect): mock_connect.side_effect = self._mock_manager self.dev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) self.device_handler = JunosDeviceHandler(device_params={ 'name': 'junos', 'local': False }) self.dev.open() self.table = Table(dev=self.dev) self.ppt = PhyPortTable(self.dev)
def setUp(self, mock_connect): mock_connect.side_effect = self._mock_manager self.dev = Device(host="1.1.1.1", user="******", password="******", gather_facts=False) self.device_handler = JunosDeviceHandler(device_params={ "name": "junos", "local": False }) self.dev.open() self.table = Table(dev=self.dev) self.ppt = PhyPortTable(self.dev)
def test_post_connect(self, mock_lock, mock_handler, mock_log): cap = [':candidate'] obj = Session(cap) device_handler = JunosDeviceHandler({'name': 'junos'}) obj._device_handler = device_handler obj._connected = True obj._id = 100 obj._server_capabilities = cap obj._post_connect() log_call = mock_log.call_args_list[0][0][0] self.assertNotEqual(log_call.find("initialized"), -1) self.assertNotEqual(log_call.find("session-id=100"), -1) self.assertNotEqual( log_call.find("server_capabilities=[':candidate']"), -1)
def test_post_connect2(self, mock_lock, mock_handler, mock_log): cap = ['urn:ietf:params:netconf:base:1.1'] obj = Session(cap) device_handler = JunosDeviceHandler({'name': 'junos'}) obj._device_handler = device_handler obj._connected = True obj._id = 100 obj._server_capabilities = cap obj._post_connect() log_args = mock_log.call_args_list[0][0] self.assertNotEqual(log_args[0].find("initialized"), -1) self.assertNotEqual(log_args[0].find("session-id="), -1) self.assertEqual(log_args[1], 100) self.assertNotEqual(log_args[0].find("server_capabilities="), -1) self.assertEqual(log_args[2], ['urn:ietf:params:netconf:base:1.1'])
def test_dispatch_message_error2(self, mock_log, mock_errback, mock_handle_raw_dispatch, mock_parse_root): mock_parse_root.side_effect = Exception mock_handle_raw_dispatch.return_value = Exception() mock_errback.side_effect = Exception cap = [':candidate'] obj = Session(cap) device_handler = JunosDeviceHandler({'name': 'junos'}) obj._device_handler = device_handler listener = HelloHandler(None, None) obj._listeners.add(listener) obj._dispatch_message(rpc_reply) mock_handle_raw_dispatch.assert_called_once_with(rpc_reply) self.assertEqual( mock_log.call_args_list[0][0][0].find("error dispatching to"), -1)
def _test_run_send_py3(self, base, chunker, mock_error, mock_selector, mock_send, mock_ready, mock_close): mock_selector.return_value = False mock_ready.return_value = True mock_send.return_value = -1 device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj._channel = paramiko.Channel("c100") msg = "naïve garçon" obj._q.put(msg) obj._base = base obj.run() self.assertEqual(mock_send.call_args_list[0][0][0], chunker(msg)) self.assertTrue( isinstance(mock_error.call_args_list[0][0][0], SessionCloseError))
def test_parse11(self, mock_dispatch): device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) if sys.version >= "3.0": obj._buffer.write(bytes(rpc_reply11, "utf-8")) remainder = bytes(reply_ok_partial_chunk, "utf-8") else: obj._buffer.write(rpc_reply11) remainder = reply_ok_partial_chunk obj.parser._parse11() expected_messages = [reply_data, reply_ok] for i in range(0, len(expected_messages)): call = mock_dispatch.call_args_list[i][0][0] self.assertEqual(call, expected_messages[i]) self.assertEqual(obj._buffer.getvalue(), remainder)
def test_parse(self, mock_dispatch): device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) if sys.version >= "3.0": b = bytes(rpc_reply, "utf-8") obj._buffer.write(b) obj._parse() dispatched_str = (b[0:509]).strip().decode("utf-8") call = mock_dispatch.call_args_list[0][0][0] self.assertEqual(call, dispatched_str) self.assertEqual(obj._buffer.getvalue(), b[515:]) else: obj._buffer.write(rpc_reply) obj._parse() dispatched_str = (rpc_reply[0:509]).strip() call = mock_dispatch.call_args_list[0][0][0] self.assertEqual(call, dispatched_str) self.assertEqual(obj._buffer.getvalue(), rpc_reply[515:])
def test_parse_incomplete_delimiter(self, mock_dispatch): device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) if sys.version >= "3.0": b = bytes(rpc_reply_part_1, "utf-8") obj._buffer.write(b) obj._parse() self.assertFalse(mock_dispatch.called) b = bytes(rpc_reply_part_2, "utf-8") obj._buffer.write(b) obj._parse() self.assertTrue(mock_dispatch.called) else: obj._buffer.write(rpc_reply_part_1) obj._parse() self.assertFalse(mock_dispatch.called) obj._buffer.write(rpc_reply_part_2) obj._parse() self.assertTrue(mock_dispatch.called)
def _test_parsemethod(self, mock_dispatch, parsemethod, reply, ok_chunk, expected_messages): device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) if sys.version >= "3.0": obj._buffer.write(bytes(reply, "utf-8")) remainder = bytes(ok_chunk, "utf-8") else: obj._buffer.write(reply) remainder = ok_chunk # parse the main reply parsemethod(obj) # parse the ok parsemethod(obj) for i in range(0, len(expected_messages)): call = mock_dispatch.call_args_list[i][0][0] self.assertEqual(call, expected_messages[i]) self.assertEqual(obj._buffer.getvalue(), remainder)
def test_load_host_key_2(self, mock_load, mock_os): mock_os.return_value = "file_name" device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj.load_known_hosts() mock_load.assert_called_once_with("file_name")
def test_load_host_key(self, mock_load): device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj.load_known_hosts("file_name") mock_load.assert_called_once_with("file_name")
def test_auth_no_methods_exception(self): device_handler = JunosDeviceHandler({'name': 'junos'}) obj = SSHSession(device_handler) obj._transport = paramiko.Transport(MagicMock()) self.assertRaises(AuthenticationError, obj._auth,'user', None, [], False, False)
def __init__(self, **kvargs): """ NoobDevice object constructor. :param str host: **REQUIRED** host-name or ipaddress of target device :param str user: *OPTIONAL* login user-name, uses root if not provided :param str passwd: *OPTIONAL* in console connection for device at zeroized state password is not required :param int port: *OPTIONAL* port, defaults to '23' for telnet mode and '/dev/ttyUSB0' for serial. :param int baud: *OPTIONAL* baud, default baud rate is 9600 :param str mode: *OPTIONAL* mode, mode of connection (telnet/serial) default is telnet :param int timeout: *OPTIONAL* timeout, default is 0.5 :param int attempts: *OPTIONAL* attempts, default is 10 :param str ssh_config: *OPTIONAL* The path to the SSH configuration file. This can be used to load SSH information from a configuration file. By default ~/.ssh/config is queried it will be used by SCP class. So its assumed ssh is enabled by the time we use SCP functionality. :param bool gather_facts: *OPTIONAL* Defaults to ``False``. If ``False`` and old-style fact gathering is in use then facts are not gathered on call to :meth:`open`. This argument is a no-op when new-style fact gathering is in use (the default.) :param str fact_style: *OPTIONAL* The style of fact gathering to use. Valid values are: 'new', 'old', or 'both'. The default is 'new'. The value 'both' is only present for debugging purposes. It will be removed in a future release. The value 'old' is only present to workaround bugs in new-style fact gathering. It will be removed in a future release. :param bool console_has_banner: *OPTIONAL* default is ``False``. If ``False`` then in case of a hung state, <close-session/> rpc is sent to the console. If ``True``, after sleep(5), a new-line is sent """ # ---------------------------------------- # setup instance connection/open variables # ---------------------------------------- self._tty = None self._ofacts = {} self.connected = False self._skip_logout = False self.results = dict(changed=False, failed=False, errmsg=None) # hostname is not required in serial mode connection self._hostname = kvargs.get("host") self._auth_user = kvargs.get("user", "root") self._conf_auth_user = None self._conf_ssh_private_key_file = None self._auth_password = kvargs.get("password", "") or kvargs.get( "passwd", "") self.cs_user = kvargs.get("cs_user") self.cs_passwd = kvargs.get("cs_passwd") self._port = kvargs.get("port", "22" if self.cs_user else "23") self._mode = kvargs.get("mode", None if self.cs_user else "telnet") self._baud = kvargs.get("baud", "9600") if self._hostname: self._ssh_config = kvargs.get("ssh_config") self._sshconf_lkup() self._ssh_private_key_file = (kvargs.get("ssh_private_key_file") or self._conf_ssh_private_key_file) self._timeout = kvargs.get("timeout", "0.5") self._normalize = kvargs.get("normalize", False) self._attempts = kvargs.get("attempts", 10) self._gather_facts = kvargs.get("gather_facts", False) self._fact_style = kvargs.get("fact_style", "new") self._huge_tree = kvargs.get("huge_tree", False) if self._fact_style != "new": warnings.warn( "fact-style %s will be removed in " "a future release." % (self._fact_style), RuntimeWarning, ) self.console_has_banner = kvargs.get("console_has_banner", False) self.rpc = _RpcMetaExec(self) self._manages = [] self.junos_dev_handler = JunosDeviceHandler(device_params={ "name": "junos", "local": False }) self._conn = None self._j2ldr = _Jinja2ldr if self._fact_style == "old": self.facts = self.ofacts else: self.facts = _FactCache(self)
def __init__(self, **kvargs): """ NoobDevice object constructor. :param str host: **REQUIRED** host-name or ipaddress of target device :param str user: *OPTIONAL* login user-name, uses root if not provided :param str passwd: *OPTIONAL* in console connection for device at zeroized state password is not required :param int port: *OPTIONAL* port, defaults to '23' for telnet mode and '/dev/ttyUSB0' for serial. :param int baud: *OPTIONAL* baud, default baud rate is 9600 :param str mode: *OPTIONAL* mode, mode of connection (telnet/serial) default is telnet :param int timeout: *OPTIONAL* timeout, default is 0.5 :param int attempts: *OPTIONAL* attempts, default is 10 :param str ssh_config: *OPTIONAL* The path to the SSH configuration file. This can be used to load SSH information from a configuration file. By default ~/.ssh/config is queried it will be used by SCP class. So its assumed ssh is enabled by the time we use SCP functionality. :param bool gather_facts: *OPTIONAL* Defaults to ``False``. If ``False`` and old-style fact gathering is in use then facts are not gathered on call to :meth:`open`. This argument is a no-op when new-style fact gathering is in use (the default.) :param str fact_style: *OPTIONAL* The style of fact gathering to use. Valid values are: 'new', 'old', or 'both'. The default is 'new'. The value 'both' is only present for debugging purposes. It will be removed in a future release. The value 'old' is only present to workaround bugs in new-style fact gathering. It will be removed in a future release. :param bool console_has_banner: *OPTIONAL* default is ``False``. If ``False`` then in case of a hung state, <close-session/> rpc is sent to the console. If ``True``, after sleep(5), a new-line is sent """ # ---------------------------------------- # setup instance connection/open variables # ---------------------------------------- self._tty = None self._ofacts = {} self.connected = False self._skip_logout = False self.results = dict(changed=False, failed=False, errmsg=None) # hostname is not required in serial mode connection self._hostname = kvargs.get('host') self._auth_user = kvargs.get('user', 'root') self._auth_password = kvargs.get('password', '') or kvargs.get( 'passwd', '') self._port = kvargs.get('port', '23') self._baud = kvargs.get('baud', '9600') self._mode = kvargs.get('mode', 'telnet') self._timeout = kvargs.get('timeout', '0.5') self._normalize = kvargs.get('normalize', False) self._norm_transform = lambda: JXML.normalize_xslt.encode('UTF-8') self.transform = self._norm_transform # self.timeout needed by PyEZ utils #self.timeout = self._timeout self._attempts = kvargs.get('attempts', 10) self._gather_facts = kvargs.get('gather_facts', False) self._fact_style = kvargs.get('fact_style', 'new') if self._fact_style != 'new': warnings.warn( 'fact-style %s will be removed in a future release.' % (self._fact_style), RuntimeWarning) self.console_has_banner = kvargs.get('console_has_banner', False) self.rpc = _RpcMetaExec(self) self._ssh_config = kvargs.get('ssh_config') self._manages = [] self.junos_dev_handler = JunosDeviceHandler(device_params={ 'name': 'junos', 'local': False }) if self._fact_style == 'old': self.facts = self.ofacts else: self.facts = _FactCache(self)
def __init__(self, **kvargs): """ NoobDevice object constructor. :param str host: **REQUIRED** host-name or ipaddress of target device :param str user: *OPTIONAL* login user-name, uses root if not provided :param str passwd: *OPTIONAL* in console connection for device at zeroized state password is not required :param int port: *OPTIONAL* port, defaults to '23' for telnet mode and '/dev/ttyUSB0' for serial. :param int baud: *OPTIONAL* baud, default baud rate is 9600 :param str mode: *OPTIONAL* mode, mode of connection (telnet/serial) default is telnet :param int timeout: *OPTIONAL* timeout, default is 0.5 :param int attempts: *OPTIONAL* attempts, default is 10 :param str ssh_config: *OPTIONAL* The path to the SSH configuration file. This can be used to load SSH information from a configuration file. By default ~/.ssh/config is queried it will be used by SCP class. So its assumed ssh is enabled by the time we use SCP functionality. :param bool gather_facts: *OPTIONAL* default is ``False``. If ``False`` then the facts are not gathered on call to :meth:`open` """ # ---------------------------------------- # setup instance connection/open variables # ---------------------------------------- self._tty = None self._facts = {} self.connected = False self._skip_logout = False self.results = dict(changed=False, failed=False, errmsg=None) # hostname is not required in serial mode connection self._hostname = kvargs.get('host') self._auth_user = kvargs.get('user', 'root') self._auth_password = kvargs.get( 'password', '') or kvargs.get( 'passwd', '') self._port = kvargs.get('port', '23') self._baud = kvargs.get('baud', '9600') self._mode = kvargs.get('mode', 'telnet') self._timeout = kvargs.get('timeout', '0.5') self._normalize = kvargs.get('normalize', False) self._norm_transform = lambda: JXML.normalize_xslt.encode('UTF-8') self.transform = self._norm_transform # self.timeout needed by PyEZ utils #self.timeout = self._timeout self._attempts = kvargs.get('attempts', 10) self.gather_facts = kvargs.get('gather_facts', False) self.rpc = _RpcMetaExec(self) self._ssh_config = kvargs.get('ssh_config') self._manages = [] self.junos_dev_handler = JunosDeviceHandler(device_params= {'name': 'junos', 'local': False})