Ejemplo n.º 1
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            file=dict(required=True),
            remote_path=dict(),
            hostname=dict(required=True),
            username=dict(required=True),
            password=dict(required=True),
            port=dict(type='int', default=830)
        ),
        supports_check_mode=False
    )

    if not HAS_PYHP:
        safe_fail(module, msg='There was a problem loading from the pyhpecw7 '
                  + 'module.', error=str(ie))

    hostname = socket.gethostbyname(module.params['hostname'])
    username = module.params['username']
    password = module.params['password']
    port = module.params['port']

    device = HPCOM7(host=hostname, username=username,
                    password=password, port=port, timeout=120)

    src = module.params.get('file')
    dst = module.params.get('remote_path')

    changed = False

    try:
        device.open()
    except ConnectionError as e:
        safe_fail(module, device, msg=str(e),
                  descr='Error opening connection to device.')

    try:
        file_copy = FileCopy(device, src, dst)
        if not file_copy.file_already_exists():
            if not file_copy.remote_dir_exists:
                file_copy.create_remote_dir()
            file_copy.transfer_file()
            changed = True
    except PYHPError as fe:
        safe_fail(module, device, msg=str(fe),
                  descr='Error transferring file.')

    results = {}
    results['source_file'] = file_copy.src
    results['destination_file'] = file_copy.dst
    results['changed'] = changed

    safe_exit(module, device, **results)
Ejemplo n.º 2
0
class FileCopyTestCase(BaseFeatureCase):

    @mock.patch('pyhpecw7.comware.HPCOM7')
    def setUp(self, mock_device):
        self.device = mock_device
        self.file_copy = FileCopy(self.device, SOURCE_FILE)

    def test_init(self):
        self.assertEqual(self.file_copy._remote_dir, 'flash:/')
        self.assertEqual(self.file_copy.src, SOURCE_FILE)
        self.assertEqual(self.file_copy.dst, 'flash:/file.txt')
        self.assertEqual(self.file_copy.port, 22)
        self.assertEqual(self.file_copy.remote_dir_exists, True)

    def test_get_flash_size(self):
        self.device.cli_display.return_value = self.read_cli_display('dir_flash')
        result = self.file_copy._get_flash_size()

        self.assertEqual(result, 742204000)

        self.device.cli_display.return_value = 'garbaldigook'
        result = self.file_copy._get_flash_size()

        self.assertEqual(result, 0)

    @mock.patch.object(FileCopy, '_get_flash_size')
    @mock.patch('os.path.getsize')
    def test_enough_space(self, mock_getsize, mock_get_flash_size):
        mock_getsize.return_value = 2
        mock_get_flash_size.return_value = 1

        with self.assertRaises(FileNotEnoughSpaceError):
            self.file_copy._enough_space()

        mock_getsize.return_value = 1
        mock_get_flash_size.return_value = 2

        result = self.file_copy._enough_space()
        self.assertEqual(result, None)

    @mock.patch.object(FileCopy, '_get_remote_md5')
    @mock.patch.object(FileCopy, '_get_local_md5')
    def test_file_already_exists(self, mock_local_md5, mock_remote_md5):
        mock_local_md5.return_value = 'abc123'
        mock_remote_md5.return_value = 'abc123'

        result = self.file_copy.file_already_exists()
        self.assertEqual(result, True)

        self.file_copy.remote_dir_exists = False
        result = self.file_copy.file_already_exists()
        self.assertEqual(result, False)

        self.file_copy.remote_dir_exists = True
        mock_remote_md5.return_value = None
        result = self.file_copy.file_already_exists()
        self.assertEqual(result, False)

        mock_remote_md5.side_effect = NCError
        result = self.file_copy.file_already_exists()
        self.assertEqual(result, False)

    @mock.patch.object(__builtin__, 'open')
    def test_safety_checks_file_not_readable(self, mock_open):
        mock_open.side_effect = IOError
        with self.assertRaises(FileNotReadableError):
            self.file_copy._safety_checks()

    @mock.patch.object(__builtin__, 'open')
    def test_safety_checks_no_remote_dir(self, mock_open):
        self.file_copy.remote_dir_exists = False
        with self.assertRaises(FileRemoteDirDoesNotExist):
            self.file_copy._safety_checks()

    @mock.patch.object(__builtin__, 'open')
    def test_safety_checks_no_remote_dir(self, mock_open):
        self.file_copy.remote_dir_exists = False
        with self.assertRaises(FileRemoteDirDoesNotExist):
            self.file_copy._safety_checks()

    @mock.patch.object(FileCopy, 'file_already_exists')
    @mock.patch.object(FileCopy, '_enough_space')
    @mock.patch.object(__builtin__, 'open')
    def test_safety_checks_no_remote_dir(self, mock_open, mock_enough_space, mock_file_already_exists):
        mock_file_already_exists.return_value = False
        self.file_copy._safety_checks()
        mock_enough_space.assert_called_with()

    def test_remote_md5(self):
        expected_get, get_reply = self.xml_action_and_reply('file_copy_remote_md5')
        self.device.action.return_value = get_reply

        expected = '44d5527772e1b9841f99cb03f31cbc1c'
        result = self.file_copy._get_remote_md5()

        self.assertEqual(result, expected)
        self.assert_action_request(expected_get)

    def test_local_md5(self):
        test_file = NamedTemporaryFile()
        self.file_copy.src = test_file.name

        test_file.write('Test content.')
        test_file.flush()

        result = self.file_copy._get_local_md5()
        self.assertEqual(result, 'bcb898f62d9e1ac765c77e6804cbd872')

        test_file.close()

    def test_remote_dir(self):
        expected_get, get_reply = self.xml_get_and_reply('file_copy_remote_dir')
        self.device.get.return_value = get_reply

        expected = True
        result = self.file_copy._remote_dir_exists()

        self.assertEqual(result, expected)
        self.assert_get_request(expected_get)


    @mock.patch('pyhpecw7.features.file_copy.paramiko')
    @mock.patch('pyhpecw7.features.file_copy.SCPClient')
    @mock.patch.object(FileCopy, '_safety_checks')
    @mock.patch.object(FileCopy, '_get_local_md5')
    @mock.patch.object(FileCopy, '_get_remote_md5')
    def test_transfer_file(self, mock_remote_md5, mock_local_md5, mock_safety_checks, mock_SCP, mock_paramiko):
        mock_remote_md5.return_value = 'abc'
        mock_local_md5.return_value = 'abc'

        mock_ssh = mock_paramiko.SSHClient.return_value

        self.file_copy.transfer_file()

        mock_paramiko.SSHClient.assert_called_with()

        mock_ssh.set_missing_host_key_policy.assert_called_with(mock_paramiko.AutoAddPolicy.return_value)
        mock_ssh.connect.assert_called_with(allow_agent=False,
                                             hostname=self.device.host,
                                             look_for_keys=False,
                                             password=self.device.password,
                                             port=22,
                                             username=self.device.username)

        mock_SCP.assert_called_with(mock_ssh.get_transport.return_value)
        mock_SCP.return_value.put.assert_called_with('/path/to/source/file.txt', 'flash:/file.txt')
        mock_SCP.return_value.close.assert_called_with()

    @mock.patch('pyhpecw7.features.file_copy.paramiko')
    @mock.patch('pyhpecw7.features.file_copy.SCPClient')
    @mock.patch.object(FileCopy, '_safety_checks')
    @mock.patch.object(FileCopy, '_get_local_md5')
    @mock.patch.object(FileCopy, '_get_remote_md5')
    def test_transfer_file_mismatch_hash(self, mock_remote_md5, mock_local_md5, mock_safety_checks, mock_SCP, mock_paramiko):
        mock_remote_md5.return_value = 'abc'
        mock_local_md5.return_value = 'def'

        mock_ssh = mock_paramiko.SSHClient.return_value

        with self.assertRaises(FileHashMismatchError):
            self.file_copy.transfer_file()

        mock_paramiko.SSHClient.assert_called_with()

        mock_ssh.set_missing_host_key_policy.assert_called_with(mock_paramiko.AutoAddPolicy.return_value)
        mock_ssh.connect.assert_called_with(allow_agent=False,
                                             hostname=self.device.host,
                                             look_for_keys=False,
                                             password=self.device.password,
                                             port=22,
                                             username=self.device.username)

        mock_SCP.assert_called_with(mock_ssh.get_transport.return_value)
        mock_SCP.return_value.put.assert_called_with('/path/to/source/file.txt', 'flash:/file.txt')
        mock_SCP.return_value.close.assert_called_with()

    @mock.patch('pyhpecw7.features.file_copy.paramiko')
    @mock.patch('pyhpecw7.features.file_copy.SCPClient')
    @mock.patch.object(FileCopy, '_safety_checks')
    @mock.patch.object(FileCopy, '_get_local_md5')
    @mock.patch.object(FileCopy, '_get_remote_md5')
    def test_transfer_file_error(self, mock_remote_md5, mock_local_md5, mock_safety_checks, mock_SCP, mock_paramiko):
        mock_remote_md5.return_value = 'abc'
        mock_local_md5.return_value = 'def'

        mock_ssh = mock_paramiko.SSHClient.return_value

        mock_SCP.return_value.put.side_effect = Exception

        with self.assertRaises(FileTransferError):
            self.file_copy.transfer_file()

        mock_paramiko.SSHClient.assert_called_with()

        mock_ssh.set_missing_host_key_policy.assert_called_with(mock_paramiko.AutoAddPolicy.return_value)
        mock_ssh.connect.assert_called_with(allow_agent=False,
                                             hostname=self.device.host,
                                             look_for_keys=False,
                                             password=self.device.password,
                                             port=22,
                                             username=self.device.username)

        mock_SCP.assert_called_with(mock_ssh.get_transport.return_value)
        mock_SCP.return_value.put.assert_called_with('/path/to/source/file.txt', 'flash:/file.txt')


    def test_create_dir(self):
        self.file_copy._remote_dir = 'flash:/unit/'

        expected_get, get_reply = self.xml_action_and_reply('file_copy_create_remote_dir')
        self.device.action.return_value = get_reply

        expected = None
        result = self.file_copy.create_remote_dir()

        self.assertEqual(result, expected)
        self.assert_action_request(expected_get)
Ejemplo n.º 3
0
class FileCopyTestCase(BaseFeatureCase):
    @mock.patch('pyhpecw7.comware.HPCOM7')
    def setUp(self, mock_device):
        self.device = mock_device
        self.file_copy = FileCopy(self.device, SOURCE_FILE)

    def test_init(self):
        self.assertEqual(self.file_copy._remote_dir, 'flash:/')
        self.assertEqual(self.file_copy.src, SOURCE_FILE)
        self.assertEqual(self.file_copy.dst, 'flash:/file.txt')
        self.assertEqual(self.file_copy.port, 22)
        self.assertEqual(self.file_copy.remote_dir_exists, True)

    def test_get_flash_size(self):
        self.device.cli_display.return_value = self.read_cli_display(
            'dir_flash')
        result = self.file_copy._get_flash_size()

        self.assertEqual(result, 742204000)

        self.device.cli_display.return_value = 'garbaldigook'
        result = self.file_copy._get_flash_size()

        self.assertEqual(result, 0)

    @mock.patch.object(FileCopy, '_get_flash_size')
    @mock.patch('os.path.getsize')
    def test_enough_space(self, mock_getsize, mock_get_flash_size):
        mock_getsize.return_value = 2
        mock_get_flash_size.return_value = 1

        with self.assertRaises(FileNotEnoughSpaceError):
            self.file_copy._enough_space()

        mock_getsize.return_value = 1
        mock_get_flash_size.return_value = 2

        result = self.file_copy._enough_space()
        self.assertEqual(result, None)

    @mock.patch.object(FileCopy, '_get_remote_md5')
    @mock.patch.object(FileCopy, '_get_local_md5')
    def test_file_already_exists(self, mock_local_md5, mock_remote_md5):
        mock_local_md5.return_value = 'abc123'
        mock_remote_md5.return_value = 'abc123'

        result = self.file_copy.file_already_exists()
        self.assertEqual(result, True)

        self.file_copy.remote_dir_exists = False
        result = self.file_copy.file_already_exists()
        self.assertEqual(result, False)

        self.file_copy.remote_dir_exists = True
        mock_remote_md5.return_value = None
        result = self.file_copy.file_already_exists()
        self.assertEqual(result, False)

        mock_remote_md5.side_effect = NCError
        result = self.file_copy.file_already_exists()
        self.assertEqual(result, False)

    @mock.patch.object(__builtin__, 'open')
    def test_safety_checks_file_not_readable(self, mock_open):
        mock_open.side_effect = IOError
        with self.assertRaises(FileNotReadableError):
            self.file_copy._safety_checks()

    @mock.patch.object(__builtin__, 'open')
    def test_safety_checks_no_remote_dir(self, mock_open):
        self.file_copy.remote_dir_exists = False
        with self.assertRaises(FileRemoteDirDoesNotExist):
            self.file_copy._safety_checks()

    @mock.patch.object(__builtin__, 'open')
    def test_safety_checks_no_remote_dir(self, mock_open):
        self.file_copy.remote_dir_exists = False
        with self.assertRaises(FileRemoteDirDoesNotExist):
            self.file_copy._safety_checks()

    @mock.patch.object(FileCopy, 'file_already_exists')
    @mock.patch.object(FileCopy, '_enough_space')
    @mock.patch.object(__builtin__, 'open')
    def test_safety_checks_no_remote_dir(self, mock_open, mock_enough_space,
                                         mock_file_already_exists):
        mock_file_already_exists.return_value = False
        self.file_copy._safety_checks()
        mock_enough_space.assert_called_with()

    def test_remote_md5(self):
        expected_get, get_reply = self.xml_action_and_reply(
            'file_copy_remote_md5')
        self.device.action.return_value = get_reply

        expected = '44d5527772e1b9841f99cb03f31cbc1c'
        result = self.file_copy._get_remote_md5()

        self.assertEqual(result, expected)
        self.assert_action_request(expected_get)

    def test_local_md5(self):
        test_file = NamedTemporaryFile()
        self.file_copy.src = test_file.name

        test_file.write('Test content.'.encode('ascii'))
        test_file.flush()

        result = self.file_copy._get_local_md5()
        self.assertEqual(result, 'bcb898f62d9e1ac765c77e6804cbd872')

        test_file.close()

    def test_remote_dir(self):
        expected_get, get_reply = self.xml_get_and_reply(
            'file_copy_remote_dir')
        self.device.get.return_value = get_reply

        expected = True
        result = self.file_copy._remote_dir_exists()

        self.assertEqual(result, expected)
        self.assert_get_request(expected_get)

    @mock.patch('pyhpecw7.features.file_copy.paramiko')
    @mock.patch('pyhpecw7.features.file_copy.SCPClient')
    @mock.patch.object(FileCopy, '_safety_checks')
    @mock.patch.object(FileCopy, '_get_local_md5')
    @mock.patch.object(FileCopy, '_get_remote_md5')
    def test_transfer_file(self, mock_remote_md5, mock_local_md5,
                           mock_safety_checks, mock_SCP, mock_paramiko):
        mock_remote_md5.return_value = 'abc'
        mock_local_md5.return_value = 'abc'

        mock_ssh = mock_paramiko.SSHClient.return_value

        self.file_copy.transfer_file()

        mock_paramiko.SSHClient.assert_called_with()

        mock_ssh.set_missing_host_key_policy.assert_called_with(
            mock_paramiko.AutoAddPolicy.return_value)
        mock_ssh.connect.assert_called_with(allow_agent=False,
                                            hostname=self.device.host,
                                            look_for_keys=False,
                                            password=self.device.password,
                                            port=22,
                                            username=self.device.username)

        mock_SCP.assert_called_with(mock_ssh.get_transport.return_value)
        mock_SCP.return_value.put.assert_called_with(
            '/path/to/source/file.txt', 'flash:/file.txt')
        mock_SCP.return_value.close.assert_called_with()

    @mock.patch('pyhpecw7.features.file_copy.paramiko')
    @mock.patch('pyhpecw7.features.file_copy.SCPClient')
    @mock.patch.object(FileCopy, '_safety_checks')
    @mock.patch.object(FileCopy, '_get_local_md5')
    @mock.patch.object(FileCopy, '_get_remote_md5')
    def test_transfer_file_mismatch_hash(self, mock_remote_md5, mock_local_md5,
                                         mock_safety_checks, mock_SCP,
                                         mock_paramiko):
        mock_remote_md5.return_value = 'abc'
        mock_local_md5.return_value = 'def'

        mock_ssh = mock_paramiko.SSHClient.return_value

        with self.assertRaises(FileHashMismatchError):
            self.file_copy.transfer_file()

        mock_paramiko.SSHClient.assert_called_with()

        mock_ssh.set_missing_host_key_policy.assert_called_with(
            mock_paramiko.AutoAddPolicy.return_value)
        mock_ssh.connect.assert_called_with(allow_agent=False,
                                            hostname=self.device.host,
                                            look_for_keys=False,
                                            password=self.device.password,
                                            port=22,
                                            username=self.device.username)

        mock_SCP.assert_called_with(mock_ssh.get_transport.return_value)
        mock_SCP.return_value.put.assert_called_with(
            '/path/to/source/file.txt', 'flash:/file.txt')
        mock_SCP.return_value.close.assert_called_with()

    @mock.patch('pyhpecw7.features.file_copy.paramiko')
    @mock.patch('pyhpecw7.features.file_copy.SCPClient')
    @mock.patch.object(FileCopy, '_safety_checks')
    @mock.patch.object(FileCopy, '_get_local_md5')
    @mock.patch.object(FileCopy, '_get_remote_md5')
    def test_transfer_file_error(self, mock_remote_md5, mock_local_md5,
                                 mock_safety_checks, mock_SCP, mock_paramiko):
        mock_remote_md5.return_value = 'abc'
        mock_local_md5.return_value = 'def'

        mock_ssh = mock_paramiko.SSHClient.return_value

        mock_SCP.return_value.put.side_effect = Exception

        with self.assertRaises(FileTransferError):
            self.file_copy.transfer_file()

        mock_paramiko.SSHClient.assert_called_with()

        mock_ssh.set_missing_host_key_policy.assert_called_with(
            mock_paramiko.AutoAddPolicy.return_value)
        mock_ssh.connect.assert_called_with(allow_agent=False,
                                            hostname=self.device.host,
                                            look_for_keys=False,
                                            password=self.device.password,
                                            port=22,
                                            username=self.device.username)

        mock_SCP.assert_called_with(mock_ssh.get_transport.return_value)
        mock_SCP.return_value.put.assert_called_with(
            '/path/to/source/file.txt', 'flash:/file.txt')

    def test_create_dir(self):
        self.file_copy._remote_dir = 'flash:/unit/'

        expected_get, get_reply = self.xml_action_and_reply(
            'file_copy_create_remote_dir')
        self.device.action.return_value = get_reply

        expected = None
        result = self.file_copy.create_remote_dir()

        self.assertEqual(result, expected)
        self.assert_action_request(expected_get)