# Copyright 2014 IBM Corp.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import time

import fixtures
from oslo_config import cfg

from tempest.common.utils.linux import remote_client
from tempest import config
from tempest.lib import exceptions as lib_exc
from tempest.tests import base
from tempest.tests import fake_config


SERVER = {
    'id': 'server_uuid',
    'name': 'fake_server',
    'status': 'ACTIVE'
}

BROKEN_SERVER = {
    'id': 'broken_server_uuid',
    'name': 'broken_server',
    'status': 'ERROR'
}


class FakeServersClient(object):

    CONSOLE_OUTPUT = "Console output for %s"

    def get_console_output(self, server_id):
        status = 'ERROR'
        for s in SERVER, BROKEN_SERVER:
            if s['id'] == server_id:
                status = s['status']
        if status == 'ERROR':
            raise lib_exc.BadRequest('Server in ERROR state')
        else:
            return dict(output=self.CONSOLE_OUTPUT % server_id)


class TestRemoteClient(base.TestCase):
    def setUp(self):
        super(TestRemoteClient, self).setUp()
        self.useFixture(fake_config.ConfigFixture())
        self.patchobject(config, 'TempestConfigPrivate',
                         fake_config.FakePrivate)
        cfg.CONF.set_default('ip_version_for_ssh', 4, group='validation')
        cfg.CONF.set_default('network_for_ssh', 'public', group='validation')
        cfg.CONF.set_default('connect_timeout', 1, group='validation')

        self.conn = remote_client.RemoteClient('127.0.0.1', 'user', 'pass')
        self.ssh_mock = self.useFixture(fixtures.MockPatchObject(self.conn,
                                                                 'ssh_client'))

    def test_write_to_console_regular_str(self):
        self.conn.write_to_console('test')
        self._assert_exec_called_with(
            'sudo sh -c "echo \\"test\\" >/dev/console"')

    def _test_write_to_console_helper(self, message, expected_call):
        self.conn.write_to_console(message)
        self._assert_exec_called_with(expected_call)

    def test_write_to_console_special_chars(self):
        self._test_write_to_console_helper(
            r'\`',
            'sudo sh -c "echo \\"\\\\\\`\\" >/dev/console"')
        self.conn.write_to_console('$')
        self._assert_exec_called_with(
            'sudo sh -c "echo \\"\\\\$\\" >/dev/console"')

    # NOTE(maurosr): The tests below end up closer to an output format
    # assurance than a test since it's basically using comand_exec to format
    # the information using gnu/linux tools.

    def _assert_exec_called_with(self, cmd):
        cmd = "set -eu -o pipefail; PATH=$PATH:/sbin; " + cmd
        self.ssh_mock.mock.exec_command.assert_called_with(cmd)

    def test_get_disks(self):
        output_lsblk = """\
NAME       MAJ:MIN    RM          SIZE RO TYPE MOUNTPOINT
sda          8:0       0  128035676160  0 disk
sdb          8:16      0 1000204886016  0 disk
sr0         11:0       1    1073741312  0 rom"""