2014-04-04 17:31:23 +04:00
|
|
|
# Copyright 2011 Justin Santa Barbara
|
|
|
|
# Copyright 2012 Hewlett-Packard Development Company, L.P.
|
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
|
2014-12-29 14:17:41 +02:00
|
|
|
import errno
|
2015-03-09 12:23:12 +00:00
|
|
|
import glob
|
2016-05-30 17:39:13 +01:00
|
|
|
import io
|
2014-04-04 17:31:23 +04:00
|
|
|
import os
|
2015-05-04 10:11:57 +00:00
|
|
|
import shutil
|
2016-05-30 17:39:13 +01:00
|
|
|
import subprocess
|
|
|
|
import tarfile
|
2014-04-04 17:31:23 +04:00
|
|
|
import tempfile
|
|
|
|
|
2016-07-27 16:28:43 -04:00
|
|
|
from ironic_lib import utils as ironic_utils
|
2015-03-09 12:23:12 +00:00
|
|
|
import mock
|
2014-12-01 18:17:35 +02:00
|
|
|
from oslo_concurrency import processutils
|
2016-12-15 13:21:53 +07:00
|
|
|
from oslo_serialization import base64
|
2015-03-09 12:23:12 +00:00
|
|
|
from oslotest import base as test_base
|
2017-02-28 17:55:26 +08:00
|
|
|
import six
|
2017-02-16 09:46:08 -08:00
|
|
|
import testtools
|
2014-12-01 18:17:35 +02:00
|
|
|
|
2015-03-09 12:23:12 +00:00
|
|
|
from ironic_python_agent import errors
|
2017-04-03 15:32:44 +10:00
|
|
|
from ironic_python_agent.tests.unit import base as ironic_agent_base
|
2014-04-04 17:31:23 +04:00
|
|
|
from ironic_python_agent import utils
|
|
|
|
|
|
|
|
|
2017-04-03 15:32:44 +10:00
|
|
|
# Normally we'd use the IronicAgentTest base class which mocks out
|
|
|
|
# any use of utils.execute() to prevent accidental processes. However
|
|
|
|
# this test is checking the upcall to ironic_lib's execute(), so that
|
|
|
|
# is mocked out instead.
|
2016-07-27 16:28:43 -04:00
|
|
|
class ExecuteTestCase(test_base.BaseTestCase):
|
2014-04-04 17:31:23 +04:00
|
|
|
|
2016-07-27 16:28:43 -04:00
|
|
|
@mock.patch.object(ironic_utils, 'execute', autospec=True)
|
|
|
|
def test_execute(self, mock_execute):
|
2014-04-04 17:31:23 +04:00
|
|
|
utils.execute('/usr/bin/env', 'false', check_exit_code=False)
|
2016-07-27 16:28:43 -04:00
|
|
|
mock_execute.assert_called_once_with('/usr/bin/env', 'false',
|
|
|
|
check_exit_code=False)
|
2015-03-09 12:23:12 +00:00
|
|
|
|
|
|
|
|
2017-04-03 15:32:44 +10:00
|
|
|
class GetAgentParamsTestCase(ironic_agent_base.IronicAgentTest):
|
2015-03-09 12:23:12 +00:00
|
|
|
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch('oslo_log.log.getLogger', autospec=True)
|
|
|
|
@mock.patch('six.moves.builtins.open', autospec=True)
|
2015-03-09 12:23:12 +00:00
|
|
|
def test__read_params_from_file_fail(self, logger_mock, open_mock):
|
|
|
|
open_mock.side_effect = Exception
|
|
|
|
params = utils._read_params_from_file('file-path')
|
2016-01-12 09:03:19 +00:00
|
|
|
self.assertEqual({}, params)
|
2015-03-09 12:23:12 +00:00
|
|
|
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch('six.moves.builtins.open', autospec=True)
|
2015-03-09 12:23:12 +00:00
|
|
|
def test__read_params_from_file(self, open_mock):
|
|
|
|
kernel_line = 'api-url=http://localhost:9999 baz foo=bar\n'
|
|
|
|
open_mock.return_value.__enter__ = lambda s: s
|
|
|
|
open_mock.return_value.__exit__ = mock.Mock()
|
|
|
|
read_mock = open_mock.return_value.read
|
|
|
|
read_mock.return_value = kernel_line
|
|
|
|
params = utils._read_params_from_file('file-path')
|
|
|
|
open_mock.assert_called_once_with('file-path')
|
|
|
|
read_mock.assert_called_once_with()
|
2016-01-12 09:03:19 +00:00
|
|
|
self.assertEqual('http://localhost:9999', params['api-url'])
|
|
|
|
self.assertEqual('bar', params['foo'])
|
2016-06-16 06:40:03 -04:00
|
|
|
self.assertNotIn('baz', params)
|
2015-03-09 12:23:12 +00:00
|
|
|
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(utils, '_set_cached_params', autospec=True)
|
|
|
|
@mock.patch.object(utils, '_read_params_from_file', autospec=True)
|
|
|
|
@mock.patch.object(utils, '_get_cached_params', autospec=True)
|
2015-03-16 01:20:02 -07:00
|
|
|
def test_get_agent_params_kernel_cmdline(self, get_cache_mock,
|
|
|
|
read_params_mock,
|
|
|
|
set_cache_mock):
|
|
|
|
get_cache_mock.return_value = {}
|
2015-03-09 12:23:12 +00:00
|
|
|
expected_params = {'a': 'b'}
|
|
|
|
read_params_mock.return_value = expected_params
|
|
|
|
returned_params = utils.get_agent_params()
|
|
|
|
read_params_mock.assert_called_once_with('/proc/cmdline')
|
|
|
|
self.assertEqual(expected_params, returned_params)
|
2015-03-16 01:20:02 -07:00
|
|
|
set_cache_mock.assert_called_once_with(expected_params)
|
2015-03-09 12:23:12 +00:00
|
|
|
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(utils, '_set_cached_params', autospec=True)
|
|
|
|
@mock.patch.object(utils, '_get_vmedia_params', autospec=True)
|
|
|
|
@mock.patch.object(utils, '_read_params_from_file', autospec=True)
|
|
|
|
@mock.patch.object(utils, '_get_cached_params', autospec=True)
|
2015-03-16 01:20:02 -07:00
|
|
|
def test_get_agent_params_vmedia(self, get_cache_mock,
|
|
|
|
read_params_mock,
|
|
|
|
get_vmedia_params_mock,
|
|
|
|
set_cache_mock):
|
|
|
|
get_cache_mock.return_value = {}
|
2015-03-09 12:23:12 +00:00
|
|
|
kernel_params = {'boot_method': 'vmedia'}
|
|
|
|
vmedia_params = {'a': 'b'}
|
2015-07-15 16:08:10 +01:00
|
|
|
expected_params = dict(list(kernel_params.items()) +
|
|
|
|
list(vmedia_params.items()))
|
2015-03-09 12:23:12 +00:00
|
|
|
read_params_mock.return_value = kernel_params
|
|
|
|
get_vmedia_params_mock.return_value = vmedia_params
|
|
|
|
|
|
|
|
returned_params = utils.get_agent_params()
|
|
|
|
read_params_mock.assert_called_once_with('/proc/cmdline')
|
|
|
|
self.assertEqual(expected_params, returned_params)
|
2015-03-16 01:20:02 -07:00
|
|
|
# Make sure information is cached
|
|
|
|
set_cache_mock.assert_called_once_with(expected_params)
|
|
|
|
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(utils, '_set_cached_params', autospec=True)
|
|
|
|
@mock.patch.object(utils, '_get_cached_params', autospec=True)
|
2015-03-16 10:59:40 -07:00
|
|
|
def test_get_agent_params_from_cache(self, get_cache_mock,
|
|
|
|
set_cache_mock):
|
2015-03-16 01:20:02 -07:00
|
|
|
get_cache_mock.return_value = {'a': 'b'}
|
|
|
|
returned_params = utils.get_agent_params()
|
|
|
|
expected_params = {'a': 'b'}
|
|
|
|
self.assertEqual(expected_params, returned_params)
|
2015-03-16 10:59:40 -07:00
|
|
|
self.assertEqual(0, set_cache_mock.call_count)
|
2015-03-09 12:23:12 +00:00
|
|
|
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch('six.moves.builtins.open', autospec=True)
|
|
|
|
@mock.patch.object(glob, 'glob', autospec=True)
|
2015-03-09 12:23:12 +00:00
|
|
|
def test__get_vmedia_device(self, glob_mock, open_mock):
|
|
|
|
|
|
|
|
glob_mock.return_value = ['/sys/class/block/sda/device/model',
|
|
|
|
'/sys/class/block/sdb/device/model',
|
|
|
|
'/sys/class/block/sdc/device/model']
|
|
|
|
fobj_mock = mock.MagicMock()
|
2015-07-15 16:08:10 +01:00
|
|
|
mock_file_handle = mock.MagicMock()
|
2015-03-09 12:23:12 +00:00
|
|
|
mock_file_handle.__enter__.return_value = fobj_mock
|
|
|
|
open_mock.return_value = mock_file_handle
|
|
|
|
|
|
|
|
fobj_mock.read.side_effect = ['scsi disk', Exception, 'Virtual Media']
|
|
|
|
vmedia_device_returned = utils._get_vmedia_device()
|
|
|
|
self.assertEqual('sdc', vmedia_device_returned)
|
|
|
|
|
2015-05-04 10:11:57 +00:00
|
|
|
@mock.patch.object(shutil, 'rmtree', autospec=True)
|
|
|
|
@mock.patch.object(tempfile, 'mkdtemp', autospec=True)
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(utils, '_read_params_from_file', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(os, 'mkdir', autospec=True)
|
|
|
|
@mock.patch.object(utils, 'execute', autospec=True)
|
2016-02-03 11:23:49 +09:00
|
|
|
def test__get_vmedia_params_by_label_lower_case(
|
|
|
|
self, execute_mock, mkdir_mock, exists_mock, read_params_mock,
|
|
|
|
mkdtemp_mock, rmtree_mock):
|
2015-05-04 10:11:57 +00:00
|
|
|
mkdtemp_mock.return_value = "/tempdir"
|
2015-03-12 04:14:11 +00:00
|
|
|
|
|
|
|
null_output = ["", ""]
|
|
|
|
expected_params = {'a': 'b'}
|
|
|
|
read_params_mock.return_value = expected_params
|
2016-02-03 11:23:49 +09:00
|
|
|
exists_mock.side_effect = [True, False]
|
2015-03-12 04:14:11 +00:00
|
|
|
execute_mock.side_effect = [null_output, null_output]
|
|
|
|
|
|
|
|
returned_params = utils._get_vmedia_params()
|
|
|
|
|
|
|
|
execute_mock.assert_any_call('mount', "/dev/disk/by-label/ir-vfd-dev",
|
2015-05-04 10:11:57 +00:00
|
|
|
"/tempdir")
|
|
|
|
read_params_mock.assert_called_once_with("/tempdir/parameters.txt")
|
2015-03-12 04:14:11 +00:00
|
|
|
exists_mock.assert_called_once_with("/dev/disk/by-label/ir-vfd-dev")
|
2015-05-04 10:11:57 +00:00
|
|
|
execute_mock.assert_any_call('umount', "/tempdir")
|
2015-03-12 04:14:11 +00:00
|
|
|
self.assertEqual(expected_params, returned_params)
|
2015-05-04 10:11:57 +00:00
|
|
|
mkdtemp_mock.assert_called_once_with()
|
|
|
|
rmtree_mock.assert_called_once_with("/tempdir")
|
2015-03-12 04:14:11 +00:00
|
|
|
|
2016-02-03 11:23:49 +09:00
|
|
|
@mock.patch.object(shutil, 'rmtree', autospec=True)
|
|
|
|
@mock.patch.object(tempfile, 'mkdtemp', autospec=True)
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(utils, '_read_params_from_file', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(os, 'mkdir', autospec=True)
|
|
|
|
@mock.patch.object(utils, 'execute', autospec=True)
|
2016-02-03 11:23:49 +09:00
|
|
|
def test__get_vmedia_params_by_label_upper_case(
|
|
|
|
self, execute_mock, mkdir_mock, exists_mock, read_params_mock,
|
|
|
|
mkdtemp_mock, rmtree_mock):
|
|
|
|
mkdtemp_mock.return_value = "/tempdir"
|
|
|
|
|
|
|
|
null_output = ["", ""]
|
|
|
|
expected_params = {'a': 'b'}
|
|
|
|
read_params_mock.return_value = expected_params
|
|
|
|
exists_mock.side_effect = [False, True]
|
|
|
|
execute_mock.side_effect = [null_output, null_output]
|
|
|
|
|
|
|
|
returned_params = utils._get_vmedia_params()
|
|
|
|
|
|
|
|
execute_mock.assert_any_call('mount', "/dev/disk/by-label/IR-VFD-DEV",
|
|
|
|
"/tempdir")
|
|
|
|
read_params_mock.assert_called_once_with("/tempdir/parameters.txt")
|
|
|
|
exists_mock.assert_has_calls(
|
|
|
|
[mock.call("/dev/disk/by-label/ir-vfd-dev"),
|
|
|
|
mock.call("/dev/disk/by-label/IR-VFD-DEV")])
|
|
|
|
execute_mock.assert_any_call('umount', "/tempdir")
|
|
|
|
self.assertEqual(expected_params, returned_params)
|
|
|
|
mkdtemp_mock.assert_called_once_with()
|
|
|
|
rmtree_mock.assert_called_once_with("/tempdir")
|
|
|
|
|
2015-05-04 10:11:57 +00:00
|
|
|
@mock.patch.object(shutil, 'rmtree', autospec=True)
|
|
|
|
@mock.patch.object(tempfile, 'mkdtemp', autospec=True)
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(utils, '_get_vmedia_device', autospec=True)
|
|
|
|
@mock.patch.object(utils, '_read_params_from_file', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(os, 'mkdir', autospec=True)
|
|
|
|
@mock.patch.object(utils, 'execute', autospec=True)
|
2015-03-12 04:14:11 +00:00
|
|
|
def test__get_vmedia_params_by_device(self, execute_mock, mkdir_mock,
|
|
|
|
exists_mock, read_params_mock,
|
2015-05-04 10:11:57 +00:00
|
|
|
get_device_mock, mkdtemp_mock,
|
|
|
|
rmtree_mock):
|
|
|
|
mkdtemp_mock.return_value = "/tempdir"
|
2015-03-09 12:23:12 +00:00
|
|
|
|
|
|
|
null_output = ["", ""]
|
|
|
|
expected_params = {'a': 'b'}
|
|
|
|
read_params_mock.return_value = expected_params
|
2016-02-03 11:23:49 +09:00
|
|
|
exists_mock.side_effect = [False, False]
|
2015-03-09 12:23:12 +00:00
|
|
|
execute_mock.side_effect = [null_output, null_output]
|
|
|
|
get_device_mock.return_value = "sda"
|
|
|
|
|
|
|
|
returned_params = utils._get_vmedia_params()
|
|
|
|
|
2016-02-03 11:23:49 +09:00
|
|
|
exists_mock.assert_has_calls(
|
|
|
|
[mock.call("/dev/disk/by-label/ir-vfd-dev"),
|
|
|
|
mock.call("/dev/disk/by-label/IR-VFD-DEV")])
|
2015-03-12 04:14:11 +00:00
|
|
|
execute_mock.assert_any_call('mount', "/dev/sda",
|
2015-05-04 10:11:57 +00:00
|
|
|
"/tempdir")
|
|
|
|
read_params_mock.assert_called_once_with("/tempdir/parameters.txt")
|
|
|
|
execute_mock.assert_any_call('umount', "/tempdir")
|
2015-03-09 12:23:12 +00:00
|
|
|
self.assertEqual(expected_params, returned_params)
|
2015-05-04 10:11:57 +00:00
|
|
|
mkdtemp_mock.assert_called_once_with()
|
|
|
|
rmtree_mock.assert_called_once_with("/tempdir")
|
2015-03-09 12:23:12 +00:00
|
|
|
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(utils, '_get_vmedia_device', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
2015-03-12 04:14:11 +00:00
|
|
|
def test__get_vmedia_params_cannot_find_dev(self, exists_mock,
|
|
|
|
get_device_mock):
|
2015-03-09 12:23:12 +00:00
|
|
|
get_device_mock.return_value = None
|
2015-03-12 04:14:11 +00:00
|
|
|
exists_mock.return_value = False
|
2015-03-09 12:23:12 +00:00
|
|
|
self.assertRaises(errors.VirtualMediaBootError,
|
|
|
|
utils._get_vmedia_params)
|
|
|
|
|
2015-05-04 10:11:57 +00:00
|
|
|
@mock.patch.object(shutil, 'rmtree', autospec=True)
|
|
|
|
@mock.patch.object(tempfile, 'mkdtemp', autospec=True)
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(utils, '_get_vmedia_device', autospec=True)
|
|
|
|
@mock.patch.object(utils, '_read_params_from_file', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(os, 'mkdir', autospec=True)
|
|
|
|
@mock.patch.object(utils, 'execute', autospec=True)
|
2015-03-09 12:23:12 +00:00
|
|
|
def test__get_vmedia_params_mount_fails(self, execute_mock,
|
2015-03-12 04:14:11 +00:00
|
|
|
mkdir_mock, exists_mock,
|
|
|
|
read_params_mock,
|
2015-05-04 10:11:57 +00:00
|
|
|
get_device_mock, mkdtemp_mock,
|
|
|
|
rmtree_mock):
|
|
|
|
mkdtemp_mock.return_value = "/tempdir"
|
2015-03-09 12:23:12 +00:00
|
|
|
|
|
|
|
expected_params = {'a': 'b'}
|
2015-03-12 04:14:11 +00:00
|
|
|
exists_mock.return_value = True
|
2015-03-09 12:23:12 +00:00
|
|
|
read_params_mock.return_value = expected_params
|
|
|
|
get_device_mock.return_value = "sda"
|
|
|
|
|
|
|
|
execute_mock.side_effect = processutils.ProcessExecutionError()
|
|
|
|
|
|
|
|
self.assertRaises(errors.VirtualMediaBootError,
|
|
|
|
utils._get_vmedia_params)
|
|
|
|
|
2015-03-12 04:14:11 +00:00
|
|
|
execute_mock.assert_any_call('mount', "/dev/disk/by-label/ir-vfd-dev",
|
2015-05-04 10:11:57 +00:00
|
|
|
"/tempdir")
|
|
|
|
mkdtemp_mock.assert_called_once_with()
|
|
|
|
rmtree_mock.assert_called_once_with("/tempdir")
|
2015-03-09 12:23:12 +00:00
|
|
|
|
2015-05-04 10:11:57 +00:00
|
|
|
@mock.patch.object(shutil, 'rmtree', autospec=True)
|
|
|
|
@mock.patch.object(tempfile, 'mkdtemp', autospec=True)
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(utils, '_get_vmedia_device', autospec=True)
|
|
|
|
@mock.patch.object(utils, '_read_params_from_file', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(os, 'mkdir', autospec=True)
|
|
|
|
@mock.patch.object(utils, 'execute', autospec=True)
|
2015-03-09 12:23:12 +00:00
|
|
|
def test__get_vmedia_params_umount_fails(self, execute_mock, mkdir_mock,
|
2015-03-12 04:14:11 +00:00
|
|
|
exists_mock, read_params_mock,
|
2015-05-04 10:11:57 +00:00
|
|
|
get_device_mock, mkdtemp_mock,
|
|
|
|
rmtree_mock):
|
|
|
|
mkdtemp_mock.return_value = "/tempdir"
|
2015-03-09 12:23:12 +00:00
|
|
|
|
|
|
|
null_output = ["", ""]
|
|
|
|
expected_params = {'a': 'b'}
|
2015-03-12 04:14:11 +00:00
|
|
|
exists_mock.return_value = True
|
2015-03-09 12:23:12 +00:00
|
|
|
read_params_mock.return_value = expected_params
|
|
|
|
get_device_mock.return_value = "sda"
|
|
|
|
|
|
|
|
execute_mock.side_effect = [null_output,
|
|
|
|
processutils.ProcessExecutionError()]
|
|
|
|
|
|
|
|
returned_params = utils._get_vmedia_params()
|
|
|
|
|
2015-03-12 04:14:11 +00:00
|
|
|
execute_mock.assert_any_call('mount', "/dev/disk/by-label/ir-vfd-dev",
|
2015-05-04 10:11:57 +00:00
|
|
|
"/tempdir")
|
|
|
|
read_params_mock.assert_called_once_with("/tempdir/parameters.txt")
|
|
|
|
execute_mock.assert_any_call('umount', "/tempdir")
|
2015-03-09 12:23:12 +00:00
|
|
|
self.assertEqual(expected_params, returned_params)
|
2015-05-04 10:11:57 +00:00
|
|
|
mkdtemp_mock.assert_called_once_with()
|
|
|
|
rmtree_mock.assert_called_once_with("/tempdir")
|
|
|
|
|
|
|
|
@mock.patch.object(shutil, 'rmtree', autospec=True)
|
|
|
|
@mock.patch.object(tempfile, 'mkdtemp', autospec=True)
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(utils, '_get_vmedia_device', autospec=True)
|
|
|
|
@mock.patch.object(utils, '_read_params_from_file', autospec=True)
|
|
|
|
@mock.patch.object(os.path, 'exists', autospec=True)
|
|
|
|
@mock.patch.object(os, 'mkdir', autospec=True)
|
|
|
|
@mock.patch.object(utils, 'execute', autospec=True)
|
2015-05-04 10:11:57 +00:00
|
|
|
def test__get_vmedia_params_rmtree_fails(self, execute_mock, mkdir_mock,
|
|
|
|
exists_mock, read_params_mock,
|
|
|
|
get_device_mock, mkdtemp_mock,
|
|
|
|
rmtree_mock):
|
|
|
|
mkdtemp_mock.return_value = "/tempdir"
|
|
|
|
rmtree_mock.side_effect = Exception
|
|
|
|
|
|
|
|
null_output = ["", ""]
|
|
|
|
expected_params = {'a': 'b'}
|
|
|
|
exists_mock.return_value = True
|
|
|
|
read_params_mock.return_value = expected_params
|
|
|
|
get_device_mock.return_value = "sda"
|
|
|
|
|
|
|
|
execute_mock.return_value = null_output
|
|
|
|
|
|
|
|
returned_params = utils._get_vmedia_params()
|
|
|
|
|
|
|
|
execute_mock.assert_any_call('mount', "/dev/disk/by-label/ir-vfd-dev",
|
|
|
|
"/tempdir")
|
|
|
|
read_params_mock.assert_called_once_with("/tempdir/parameters.txt")
|
|
|
|
execute_mock.assert_any_call('umount', "/tempdir")
|
|
|
|
self.assertEqual(expected_params, returned_params)
|
|
|
|
mkdtemp_mock.assert_called_once_with()
|
|
|
|
rmtree_mock.assert_called_once_with("/tempdir")
|
2015-03-10 11:20:40 +00:00
|
|
|
|
2015-07-24 17:23:33 +02:00
|
|
|
|
|
|
|
class TestFailures(testtools.TestCase):
|
|
|
|
def test_get_error(self):
|
|
|
|
f = utils.AccumulatedFailures()
|
|
|
|
self.assertFalse(f)
|
|
|
|
self.assertIsNone(f.get_error())
|
|
|
|
|
|
|
|
f.add('foo')
|
|
|
|
f.add('%s', 'bar')
|
|
|
|
f.add(RuntimeError('baz'))
|
|
|
|
self.assertTrue(f)
|
|
|
|
|
|
|
|
exp = ('The following errors were encountered:\n* foo\n* bar\n* baz')
|
|
|
|
self.assertEqual(exp, f.get_error())
|
|
|
|
|
|
|
|
def test_raise(self):
|
|
|
|
class FakeException(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
f = utils.AccumulatedFailures(exc_class=FakeException)
|
|
|
|
self.assertIsNone(f.raise_if_needed())
|
|
|
|
f.add('foo')
|
2016-06-21 19:56:11 +03:00
|
|
|
self.assertRaisesRegex(FakeException, 'foo', f.raise_if_needed)
|
2016-05-30 17:39:13 +01:00
|
|
|
|
|
|
|
|
|
|
|
class TestUtils(testtools.TestCase):
|
|
|
|
|
|
|
|
def _get_journalctl_output(self, mock_execute, lines=None, units=None):
|
|
|
|
contents = b'Krusty Krab'
|
|
|
|
mock_execute.return_value = (contents, '')
|
|
|
|
data = utils.get_journalctl_output(lines=lines, units=units)
|
|
|
|
|
|
|
|
cmd = ['journalctl', '--full', '--no-pager', '-b']
|
|
|
|
if lines is not None:
|
|
|
|
cmd.extend(['-n', str(lines)])
|
|
|
|
if units is not None:
|
|
|
|
[cmd.extend(['-u', u]) for u in units]
|
|
|
|
|
|
|
|
mock_execute.assert_called_once_with(*cmd, binary=True,
|
|
|
|
log_stdout=False)
|
|
|
|
self.assertEqual(contents, data.read())
|
|
|
|
|
|
|
|
@mock.patch.object(utils, 'execute', autospec=True)
|
|
|
|
def test_get_journalctl_output(self, mock_execute):
|
|
|
|
self._get_journalctl_output(mock_execute)
|
|
|
|
|
|
|
|
@mock.patch.object(utils, 'execute', autospec=True)
|
|
|
|
def test_get_journalctl_output_with_lines(self, mock_execute):
|
|
|
|
self._get_journalctl_output(mock_execute, lines=123)
|
|
|
|
|
|
|
|
@mock.patch.object(utils, 'execute', autospec=True)
|
|
|
|
def test_get_journalctl_output_with_units(self, mock_execute):
|
|
|
|
self._get_journalctl_output(mock_execute, units=['fake-unit1',
|
|
|
|
'fake-unit2'])
|
|
|
|
|
|
|
|
@mock.patch.object(utils, 'execute', autospec=True)
|
|
|
|
def test_get_journalctl_output_fail(self, mock_execute):
|
|
|
|
mock_execute.side_effect = processutils.ProcessExecutionError()
|
|
|
|
self.assertRaises(errors.CommandExecutionError,
|
|
|
|
self._get_journalctl_output, mock_execute)
|
|
|
|
|
|
|
|
def test_gzip_and_b64encode(self):
|
|
|
|
contents = b'Squidward Tentacles'
|
|
|
|
io_dict = {'fake-name': io.BytesIO(bytes(contents))}
|
|
|
|
data = utils.gzip_and_b64encode(io_dict=io_dict)
|
2017-02-28 17:55:26 +08:00
|
|
|
self.assertIsInstance(data, six.text_type)
|
2016-05-30 17:39:13 +01:00
|
|
|
|
2016-12-15 13:21:53 +07:00
|
|
|
res = io.BytesIO(base64.decode_as_bytes(data))
|
2016-05-30 17:39:13 +01:00
|
|
|
with tarfile.open(fileobj=res) as tar:
|
|
|
|
members = [(m.name, m.size) for m in tar]
|
|
|
|
self.assertEqual([('fake-name', len(contents))], members)
|
|
|
|
|
|
|
|
member = tar.extractfile('fake-name')
|
|
|
|
self.assertEqual(contents, member.read())
|
|
|
|
|
|
|
|
@mock.patch.object(utils, 'execute', autospec=True)
|
|
|
|
def test_get_command_output(self, mock_execute):
|
|
|
|
contents = b'Sandra Sandy Cheeks'
|
|
|
|
mock_execute.return_value = (contents, '')
|
|
|
|
data = utils.get_command_output(['foo'])
|
|
|
|
|
|
|
|
mock_execute.assert_called_once_with(
|
|
|
|
'foo', binary=True, log_stdout=False)
|
|
|
|
self.assertEqual(contents, data.read())
|
|
|
|
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(subprocess, 'check_call', autospec=True)
|
2016-05-30 17:39:13 +01:00
|
|
|
def test_is_journalctl_present(self, mock_call):
|
|
|
|
self.assertTrue(utils.is_journalctl_present())
|
|
|
|
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(subprocess, 'check_call', autospec=True)
|
2016-05-30 17:39:13 +01:00
|
|
|
def test_is_journalctl_present_false(self, mock_call):
|
|
|
|
os_error = OSError()
|
|
|
|
os_error.errno = errno.ENOENT
|
|
|
|
mock_call.side_effect = os_error
|
|
|
|
self.assertFalse(utils.is_journalctl_present())
|
|
|
|
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(utils, 'gzip_and_b64encode', autospec=True)
|
|
|
|
@mock.patch.object(utils, 'is_journalctl_present', autospec=True)
|
|
|
|
@mock.patch.object(utils, 'get_command_output', autospec=True)
|
|
|
|
@mock.patch.object(utils, 'get_journalctl_output', autospec=True)
|
2016-05-30 17:39:13 +01:00
|
|
|
def test_collect_system_logs_journald(
|
|
|
|
self, mock_logs, mock_outputs, mock_journalctl, mock_gzip_b64):
|
|
|
|
mock_journalctl.return_value = True
|
|
|
|
ret = 'Patrick Star'
|
|
|
|
mock_gzip_b64.return_value = ret
|
|
|
|
|
|
|
|
logs_string = utils.collect_system_logs()
|
|
|
|
self.assertEqual(ret, logs_string)
|
|
|
|
mock_logs.assert_called_once_with(lines=None)
|
2016-07-07 13:38:45 +01:00
|
|
|
calls = [mock.call(['ps', 'au']), mock.call(['df', '-a']),
|
2016-05-30 17:39:13 +01:00
|
|
|
mock.call(['iptables', '-L']), mock.call(['ip', 'addr'])]
|
|
|
|
mock_outputs.assert_has_calls(calls, any_order=True)
|
|
|
|
mock_gzip_b64.assert_called_once_with(
|
|
|
|
file_list=[],
|
|
|
|
io_dict={'journal': mock.ANY, 'ip_addr': mock.ANY, 'ps': mock.ANY,
|
|
|
|
'df': mock.ANY, 'iptables': mock.ANY})
|
|
|
|
|
2017-03-19 08:30:25 -07:00
|
|
|
@mock.patch.object(utils, 'gzip_and_b64encode', autospec=True)
|
|
|
|
@mock.patch.object(utils, 'is_journalctl_present', autospec=True)
|
|
|
|
@mock.patch.object(utils, 'get_command_output', autospec=True)
|
2016-05-30 17:39:13 +01:00
|
|
|
def test_collect_system_logs_non_journald(
|
|
|
|
self, mock_outputs, mock_journalctl, mock_gzip_b64):
|
|
|
|
mock_journalctl.return_value = False
|
|
|
|
ret = 'SpongeBob SquarePants'
|
|
|
|
mock_gzip_b64.return_value = ret
|
|
|
|
|
|
|
|
logs_string = utils.collect_system_logs()
|
|
|
|
self.assertEqual(ret, logs_string)
|
2016-07-07 13:38:45 +01:00
|
|
|
calls = [mock.call(['dmesg']), mock.call(['ps', 'au']),
|
2016-05-30 17:39:13 +01:00
|
|
|
mock.call(['df', '-a']), mock.call(['iptables', '-L']),
|
|
|
|
mock.call(['ip', 'addr'])]
|
|
|
|
mock_outputs.assert_has_calls(calls, any_order=True)
|
|
|
|
mock_gzip_b64.assert_called_once_with(
|
|
|
|
file_list=['/var/log'],
|
|
|
|
io_dict={'iptables': mock.ANY, 'ip_addr': mock.ANY, 'ps': mock.ANY,
|
|
|
|
'dmesg': mock.ANY, 'df': mock.ANY})
|
2016-11-17 13:26:28 +02:00
|
|
|
|
|
|
|
def test_get_ssl_client_options(self):
|
|
|
|
# defaults
|
|
|
|
conf = mock.Mock(insecure=False, cafile=None,
|
|
|
|
keyfile=None, certfile=None)
|
|
|
|
self.assertEqual((True, None), utils.get_ssl_client_options(conf))
|
|
|
|
|
|
|
|
# insecure=True overrides cafile
|
|
|
|
conf = mock.Mock(insecure=True, cafile='spam',
|
|
|
|
keyfile=None, certfile=None)
|
|
|
|
self.assertEqual((False, None), utils.get_ssl_client_options(conf))
|
|
|
|
|
|
|
|
# cafile returned as verify when not insecure
|
|
|
|
conf = mock.Mock(insecure=False, cafile='spam',
|
|
|
|
keyfile=None, certfile=None)
|
|
|
|
self.assertEqual(('spam', None), utils.get_ssl_client_options(conf))
|
|
|
|
|
|
|
|
# only both certfile and keyfile produce non-None result
|
|
|
|
conf = mock.Mock(insecure=False, cafile=None,
|
|
|
|
keyfile=None, certfile='ham')
|
|
|
|
self.assertEqual((True, None), utils.get_ssl_client_options(conf))
|
|
|
|
|
|
|
|
conf = mock.Mock(insecure=False, cafile=None,
|
|
|
|
keyfile='ham', certfile=None)
|
|
|
|
self.assertEqual((True, None), utils.get_ssl_client_options(conf))
|
|
|
|
|
|
|
|
conf = mock.Mock(insecure=False, cafile=None,
|
|
|
|
keyfile='spam', certfile='ham')
|
|
|
|
self.assertEqual((True, ('ham', 'spam')),
|
|
|
|
utils.get_ssl_client_options(conf))
|