From b6ab3167dc647bf29999e5764da00a3b0bf650e2 Mon Sep 17 00:00:00 2001 From: Julia Varlamova Date: Mon, 6 Apr 2015 15:23:26 +0300 Subject: [PATCH] Use entry_points for manila scripts Manila scripts located in bin/* should be covered with unit tests. In order to add unit tests for bin/* scripts: - all - api - manage - scheduler - share we move them into manila/cmd and use pbr to setup console scripts which will call the respective main function of each script under manila/cmd. It will allow us to import from manila.cmd and individually test each 'main' function. Add unit tests for manila/cmd/* scripts. Implements bp unit-tests-for-manila-scripts Change-Id: I9be6b948a6de7ba76405411e98d7531cf225b57e --- manila/cmd/__init__.py | 0 bin/manila-all => manila/cmd/all.py | 19 +- bin/manila-api => manila/cmd/api.py | 18 +- bin/manila-manage => manila/cmd/manage.py | 52 +-- .../cmd/scheduler.py | 20 +- bin/manila-share => manila/cmd/share.py | 24 +- manila/test.py | 2 + manila/tests/cmd/__init__.py | 0 manila/tests/cmd/test_all.py | 84 ++++ manila/tests/cmd/test_api.py | 46 +++ manila/tests/cmd/test_manage.py | 374 ++++++++++++++++++ manila/tests/cmd/test_scheduler.py | 45 +++ manila/tests/cmd/test_share.py | 64 +++ setup.cfg | 12 +- tox.ini | 1 - 15 files changed, 674 insertions(+), 87 deletions(-) create mode 100644 manila/cmd/__init__.py rename bin/manila-all => manila/cmd/all.py (83%) rename bin/manila-api => manila/cmd/api.py (80%) rename bin/manila-manage => manila/cmd/manage.py (91%) rename bin/manila-scheduler => manila/cmd/scheduler.py (71%) rename bin/manila-share => manila/cmd/share.py (71%) create mode 100644 manila/tests/cmd/__init__.py create mode 100644 manila/tests/cmd/test_all.py create mode 100644 manila/tests/cmd/test_api.py create mode 100644 manila/tests/cmd/test_manage.py create mode 100644 manila/tests/cmd/test_scheduler.py create mode 100644 manila/tests/cmd/test_share.py diff --git a/manila/cmd/__init__.py b/manila/cmd/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/bin/manila-all b/manila/cmd/all.py similarity index 83% rename from bin/manila-all rename to manila/cmd/all.py index 94c860314b..c5d6641d65 100755 --- a/bin/manila-all +++ b/manila/cmd/all.py @@ -29,33 +29,28 @@ continue attempting to launch the rest of the services. import eventlet eventlet.monkey_patch() -import os import sys from oslo_config import cfg -possible_topdir = os.path.normpath(os.path.join - (os.path.abspath(sys.argv[0]), - os.pardir, os.pardir)) -if os.path.exists(os.path.join(possible_topdir, "manila", "__init__.py")): - sys.path.insert(0, possible_topdir) +from oslo_log import log from manila import i18n i18n.enable_lazy() from manila.common import config # Need to register global_opts # noqa from manila.i18n import _LE -from manila.openstack.common import log as logging from manila import service from manila import utils from manila import version CONF = cfg.CONF -if __name__ == '__main__': + +def main(): CONF(sys.argv[1:], project='manila', version=version.version_string()) - logging.setup("manila") - LOG = logging.getLogger('manila.all') + log.setup(CONF, "manila") + LOG = log.getLogger('manila.all') utils.monkey_patch() servers = [] @@ -72,3 +67,7 @@ if __name__ == '__main__': LOG.exception(_LE('Failed to load %s'), binary) service.serve(*servers) service.wait() + + +if __name__ == '__main__': + main() diff --git a/bin/manila-api b/manila/cmd/api.py similarity index 80% rename from bin/manila-api rename to manila/cmd/api.py index a05501bf40..f97715c96f 100755 --- a/bin/manila-api +++ b/manila/cmd/api.py @@ -25,34 +25,32 @@ import eventlet eventlet.monkey_patch() -import os import sys from oslo_config import cfg - -possible_topdir = os.path.normpath(os.path.join - (os.path.abspath(sys.argv[0]), - os.pardir, os.pardir)) -if os.path.exists(os.path.join(possible_topdir, "manila", "__init__.py")): - sys.path.insert(0, possible_topdir) +from oslo_log import log from manila import i18n i18n.enable_lazy() from manila.common import config # Need to register global_opts # noqa -from manila.openstack.common import log as logging from manila import service from manila import utils from manila import version CONF = cfg.CONF -if __name__ == '__main__': + +def main(): CONF(sys.argv[1:], project='manila', version=version.version_string()) config.verify_share_protocols() - logging.setup("manila") + log.setup(CONF, "manila") utils.monkey_patch() server = service.WSGIService('osapi_share') service.serve(server) service.wait() + + +if __name__ == '__main__': + main() diff --git a/bin/manila-manage b/manila/cmd/manage.py similarity index 91% rename from bin/manila-manage rename to manila/cmd/manage.py index 90852d17a9..677f583ed2 100755 --- a/bin/manila-manage +++ b/manila/cmd/manage.py @@ -58,27 +58,19 @@ from __future__ import print_function import os import sys - -# If ../manila/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'manila', '__init__.py')): - sys.path.insert(0, POSSIBLE_TOPDIR) - from manila import i18n i18n.enable_lazy() from oslo_config import cfg +from oslo_log import log from oslo_utils import uuidutils +import six from manila.common import config # Need to register global_opts # noqa from manila import context from manila import db from manila.db import migration from manila.i18n import _ -from manila.openstack.common import log as logging from manila import utils from manila import version @@ -145,13 +137,20 @@ class ShellCommands(object): shell = 'ipython' if shell == 'ipython': try: - import IPython - # Explicitly pass an empty list as arguments, because - # otherwise IPython would use sys.argv from this script. - shell = IPython.Shell.IPShell(argv=[]) - shell.mainloop() + from IPython import embed + embed() except ImportError: - shell = 'python' + # Ipython < 0.11 + try: + import IPython + + # Explicitly pass an empty list as arguments, because + # otherwise IPython would use sys.argv from this script. + shell = IPython.Shell.IPShell(argv=[]) + shell.mainloop() + except ImportError: + # no IPython module + shell = 'python' if shell == 'python': import code @@ -176,14 +175,6 @@ class ShellCommands(object): exec(compile(open(path).read(), path, 'exec'), locals(), globals()) -def _db_error(caught_exception): - print(caught_exception) - print(_("The above error may show that the database has not " - "been created.\nPlease create a database using " - "'manila-manage db sync' before running this command.")) - exit(1) - - class HostCommands(object): """List hosts.""" @@ -253,9 +244,6 @@ class DbCommands(object): class VersionCommands(object): """Class for exposing the codebase version.""" - def __init__(self): - pass - def list(self): print(version.version_string()) @@ -266,11 +254,8 @@ class VersionCommands(object): class ConfigCommands(object): """Class for exposing the flags defined by flag_file(s).""" - def __init__(self): - pass - def list(self): - for key, value in CONF.iteritems(): + for key, value in six.iteritems(CONF): if value is not None: print('%s = %s' % (key, value)) @@ -410,7 +395,7 @@ def get_arg_string(args): # This is long optional arg arg = args[2:] else: - arg = args[3:] + arg = args[1:] else: arg = args @@ -442,7 +427,7 @@ def main(): try: CONF(sys.argv[1:], project='manila', version=version.version_string()) - logging.setup("manila") + log.setup(CONF, "manila") except cfg.ConfigFilesNotFoundError: cfgfile = CONF.config_file[-1] if CONF.config_file else None if cfgfile and not os.access(cfgfile, os.R_OK): @@ -461,5 +446,6 @@ def main(): fn_args = fetch_func_args(fn) fn(*fn_args) + if __name__ == '__main__': main() diff --git a/bin/manila-scheduler b/manila/cmd/scheduler.py similarity index 71% rename from bin/manila-scheduler rename to manila/cmd/scheduler.py index 25b30a72f5..181869094f 100755 --- a/bin/manila-scheduler +++ b/manila/cmd/scheduler.py @@ -21,34 +21,30 @@ import eventlet eventlet.monkey_patch() -import os import sys from oslo_config import cfg - -# If ../manila/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'manila', '__init__.py')): - sys.path.insert(0, possible_topdir) +from oslo_log import log from manila import i18n i18n.enable_lazy() from manila.common import config # Need to register global_opts # noqa -from manila.openstack.common import log as logging from manila import service from manila import utils from manila import version CONF = cfg.CONF -if __name__ == '__main__': + +def main(): CONF(sys.argv[1:], project='manila', version=version.version_string()) - logging.setup("manila") + log.setup(CONF, "manila") utils.monkey_patch() server = service.Service.create(binary='manila-scheduler') service.serve(server) service.wait() + + +if __name__ == '__main__': + main() diff --git a/bin/manila-share b/manila/cmd/share.py similarity index 71% rename from bin/manila-share rename to manila/cmd/share.py index 87fab581ff..e97e79fd03 100755 --- a/bin/manila-share +++ b/manila/cmd/share.py @@ -20,34 +20,26 @@ import eventlet eventlet.monkey_patch() -import os import sys from oslo_config import cfg - -# If ../manila/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'manila', '__init__.py')): - sys.path.insert(0, possible_topdir) +from oslo_log import log from manila import i18n i18n.enable_lazy() from manila.common import config # Need to register global_opts # noqa -from manila.openstack.common import log as logging from manila import service from manila import utils from manila import version CONF = cfg.CONF -if __name__ == '__main__': - args = CONF(sys.argv[1:], project='manila', - version=version.version_string()) - logging.setup("manila") + +def main(): + CONF(sys.argv[1:], project='manila', + version=version.version_string()) + log.setup(CONF, "manila") utils.monkey_patch() launcher = service.ProcessLauncher() if CONF.enabled_share_backends: @@ -61,3 +53,7 @@ if __name__ == '__main__': server = service.Service.create(binary='manila-share') launcher.launch_server(server) launcher.wait() + + +if __name__ == '__main__': + main() diff --git a/manila/test.py b/manila/test.py index a33ce02f57..8843ce90e3 100644 --- a/manila/test.py +++ b/manila/test.py @@ -30,6 +30,7 @@ import mock from oslo_concurrency import lockutils from oslo_config import cfg from oslo_config import fixture as config_fixture +import oslo_i18n from oslo_log import log from oslo_messaging import conffixture as messaging_conffixture import oslotest.base as base_test @@ -108,6 +109,7 @@ class TestCase(base_test.BaseTestCase): """Run before each test method to initialize test environment.""" super(TestCase, self).setUp() + oslo_i18n.enable_lazy(enable=False) conf_fixture.set_defaults(CONF) CONF([], default_config_files=[]) diff --git a/manila/tests/cmd/__init__.py b/manila/tests/cmd/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/manila/tests/cmd/test_all.py b/manila/tests/cmd/test_all.py new file mode 100644 index 0000000000..b18da9d18a --- /dev/null +++ b/manila/tests/cmd/test_all.py @@ -0,0 +1,84 @@ +# Copyright 2015 Mirantis Inc. +# All Rights Reserved. +# +# 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 sys + +import ddt +import mock +from oslo_log import log + +from manila.cmd import all as manila_all +from manila import service +from manila import test +from manila import utils +from manila import version + +CONF = manila_all.CONF + + +@ddt.ddt +class ManilaCmdAllTestCase(test.TestCase): + def setUp(self): + super(ManilaCmdAllTestCase, self).setUp() + sys.argv = ['manila-all'] + + self.mock_object(log, 'setup') + self.mock_object(log, 'getLogger') + self.mock_object(utils, 'monkey_patch') + self.mock_object(service, 'WSGIService') + self.mock_object(service.Service, 'create') + self.mock_object(service, 'serve') + self.mock_object(service, 'wait') + self.wsgi_service = service.WSGIService.return_value + self.service = service.Service.create.return_value + self.fake_log = log.getLogger.return_value + + def _common_checks(self): + self.assertEqual(CONF.project, 'manila') + self.assertEqual(CONF.version, version.version_string()) + log.setup.assert_called_once_with(CONF, "manila") + log.getLogger.assert_called_once_with('manila.all') + utils.monkey_patch.assert_called_once_with() + service.WSGIService.assert_called_once_with('osapi_share') + service.wait.assert_called_once_with() + + def test_main(self): + manila_all.main() + + self._common_checks() + self.assertFalse(self.fake_log.exception.called) + service.serve.assert_has_calls([ + mock.call(self.wsgi_service, *[self.service] * 3) + ]) + + @ddt.data(Exception(), SystemExit()) + def test_main_wsgi_service_osapi_share_exception(self, exc): + service.WSGIService.side_effect = exc + + manila_all.main() + + self._common_checks() + self.fake_log.exception.assert_called_once_with(mock.ANY) + service.serve.assert_has_calls([mock.call(*[self.service] * 3)]) + + @ddt.data(Exception(), SystemExit()) + def test_main_service_create_exception(self, exc): + service.Service.create.side_effect = exc + + manila_all.main() + + self._common_checks() + self.fake_log.exception.assert_has_calls(mock.ANY) + service.serve.assert_has_calls([mock.call(self.wsgi_service)]) diff --git a/manila/tests/cmd/test_api.py b/manila/tests/cmd/test_api.py new file mode 100644 index 0000000000..620ec71570 --- /dev/null +++ b/manila/tests/cmd/test_api.py @@ -0,0 +1,46 @@ +# Copyright 2015 Mirantis Inc. +# All Rights Reserved. +# +# 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 sys + +from manila.cmd import api as manila_api +from manila import test +from manila import version + +CONF = manila_api.CONF + + +class ManilaCmdApiTestCase(test.TestCase): + def setUp(self): + super(ManilaCmdApiTestCase, self).setUp() + sys.argv = ['manila-api'] + + def test_main(self): + self.mock_object(manila_api.log, 'setup') + self.mock_object(manila_api.utils, 'monkey_patch') + self.mock_object(manila_api.service, 'WSGIService') + self.mock_object(manila_api.service, 'serve') + self.mock_object(manila_api.service, 'wait') + + manila_api.main() + + self.assertEqual(CONF.project, 'manila') + self.assertEqual(CONF.version, version.version_string()) + manila_api.log.setup.assert_called_once_with(CONF, "manila") + manila_api.utils.monkey_patch.assert_called_once_with() + manila_api.service.WSGIService.assert_called_once_with('osapi_share') + manila_api.service.wait.assert_called_once_with() + manila_api.service.serve.assert_called_once_with( + manila_api.service.WSGIService.return_value) diff --git a/manila/tests/cmd/test_manage.py b/manila/tests/cmd/test_manage.py new file mode 100644 index 0000000000..e6d29a195b --- /dev/null +++ b/manila/tests/cmd/test_manage.py @@ -0,0 +1,374 @@ +# Copyright 2015 Mirantis Inc. +# All Rights Reserved. +# +# 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 code +import readline +import StringIO +import sys + +import ddt +import mock +from oslo_config import cfg + +from manila.cmd import manage as manila_manage +from manila import context +from manila import db +from manila.db import migration +from manila import test +from manila import version + +CONF = cfg.CONF + + +@ddt.ddt +class ManilaCmdManageTestCase(test.TestCase): + def setUp(self): + super(ManilaCmdManageTestCase, self).setUp() + sys.argv = ['manila-share'] + CONF(sys.argv[1:], project='manila', version=version.version_string()) + self.shell_commands = manila_manage.ShellCommands() + self.host_commands = manila_manage.HostCommands() + self.db_commands = manila_manage.DbCommands() + self.version_commands = manila_manage.VersionCommands() + self.config_commands = manila_manage.ConfigCommands() + self.get_log_cmds = manila_manage.GetLogCommands() + self.service_cmds = manila_manage.ServiceCommands() + + def test_param2id_is_uuid_like(self): + obj_id = '12345678123456781234567812345678' + self.assertEqual(obj_id, manila_manage.param2id(obj_id)) + + def test_param2id_not_uuid_like_with_dash(self): + obj_id = '112-112-112' + self.assertIsNone(manila_manage.param2id(obj_id)) + + def test_param2id_not_uuid_like_without_dash(self): + obj_id = '123' + self.assertEqual(123, manila_manage.param2id(obj_id)) + + def test_param2id_not_uuid_like_value_error(self): + obj_id = 'invalidvalue' + self.assertRaises(ValueError, manila_manage.param2id, obj_id) + + @mock.patch.object(manila_manage.ShellCommands, 'run', mock.Mock()) + def test_shell_commands_bpython(self): + self.shell_commands.bpython() + manila_manage.ShellCommands.run.assert_called_once_with('bpython') + + @mock.patch.object(manila_manage.ShellCommands, 'run', mock.Mock()) + def test_shell_commands_ipython(self): + self.shell_commands.ipython() + manila_manage.ShellCommands.run.assert_called_once_with('ipython') + + @mock.patch.object(manila_manage.ShellCommands, 'run', mock.Mock()) + def test_shell_commands_python(self): + self.shell_commands.python() + manila_manage.ShellCommands.run.assert_called_once_with('python') + + @ddt.data({}, {'shell': 'bpython'}) + def test_run_bpython(self, kwargs): + try: + import bpython + except ImportError as e: + self.skipTest(e.message) + self.mock_object(bpython, 'embed') + self.shell_commands.run(**kwargs) + bpython.embed.assert_called_once_with() + + def test_run_bpython_import_error(self): + try: + import bpython + import IPython + except ImportError as e: + self.skipTest(e.message) + self.mock_object(bpython, 'embed', + mock.Mock(side_effect=ImportError())) + self.mock_object(IPython, 'embed') + + self.shell_commands.run(shell='bpython') + + IPython.embed.assert_called_once_with() + + def test_run(self): + try: + import bpython + except ImportError as e: + self.skipTest(e.message) + self.mock_object(bpython, 'embed') + + self.shell_commands.run() + + bpython.embed.assert_called_once_with() + + def test_run_ipython(self): + try: + import IPython + except ImportError as e: + self.skipTest(e.message) + self.mock_object(IPython, 'embed') + + self.shell_commands.run(shell='ipython') + + IPython.embed.assert_called_once_with() + + def test_run_ipython_import_error(self): + try: + import IPython + if not hasattr(IPython, 'Shell'): + setattr(IPython, 'Shell', mock.Mock()) + setattr(IPython.Shell, 'IPShell', + mock.Mock(side_effect=ImportError())) + except ImportError as e: + self.skipTest(e.message) + self.mock_object(IPython, 'embed', + mock.Mock(side_effect=ImportError())) + self.mock_object(readline, 'parse_and_bind') + self.mock_object(code, 'interact') + shell = IPython.embed.return_value + + self.shell_commands.run(shell='ipython') + IPython.Shell.IPShell.assert_called_once_with(argv=[]) + self.assertFalse(shell.mainloop.called) + self.assertTrue(readline.parse_and_bind.called) + code.interact.assert_called_once_with() + + def test_run_python(self): + self.mock_object(readline, 'parse_and_bind') + self.mock_object(code, 'interact') + + self.shell_commands.run(shell='python') + + readline.parse_and_bind.assert_called_once_with("tab:complete") + code.interact.assert_called_once_with() + + def test_run_python_import_error(self): + self.mock_object(readline, 'parse_and_bind') + self.mock_object(code, 'interact') + + self.shell_commands.run(shell='python') + + readline.parse_and_bind.assert_called_once_with("tab:complete") + code.interact.assert_called_once_with() + + @mock.patch('__builtin__.print') + def test_list(self, print_mock): + serv_1 = { + 'host': 'fake_host1', + 'availability_zone': 'avail_zone1', + } + serv_2 = { + 'host': 'fake_host2', + 'availability_zone': 'avail_zone2', + } + self.mock_object(db, 'service_get_all', + mock.Mock(return_value=[serv_1, serv_2])) + self.mock_object(context, 'get_admin_context', + mock.Mock(return_value='admin_ctxt')) + + self.host_commands.list(zone='avail_zone1') + context.get_admin_context.assert_called_once_with() + db.service_get_all.assert_called_once_with('admin_ctxt') + print_mock.assert_has_calls([ + mock.call(u'host \tzone '), + mock.call('fake_host1 \tavail_zone1 ')]) + + @mock.patch('__builtin__.print') + def test_list_zone_is_none(self, print_mock): + serv_1 = { + 'host': 'fake_host1', + 'availability_zone': 'avail_zone1', + } + serv_2 = { + 'host': 'fake_host2', + 'availability_zone': 'avail_zone2', + } + self.mock_object(db, 'service_get_all', + mock.Mock(return_value=[serv_1, serv_2])) + self.mock_object(context, 'get_admin_context', + mock.Mock(return_value='admin_ctxt')) + + self.host_commands.list() + context.get_admin_context.assert_called_once_with() + db.service_get_all.assert_called_once_with('admin_ctxt') + print_mock.assert_has_calls([ + mock.call(u'host \tzone '), + mock.call('fake_host1 \tavail_zone1 '), + mock.call('fake_host2 \tavail_zone2 ')]) + + def test_sync(self): + self.mock_object(migration, 'upgrade') + self.db_commands.sync(version='123') + migration.upgrade.assert_called_once_with('123') + + def test_version(self): + self.mock_object(migration, 'version') + self.db_commands.version() + migration.version.assert_called_once_with() + + def test_downgrade(self): + self.mock_object(migration, 'downgrade') + self.db_commands.downgrade(version='123') + migration.downgrade.assert_called_once_with('123') + + def test_revision(self): + self.mock_object(migration, 'revision') + self.db_commands.revision('message', True) + migration.revision.assert_called_once_with('message', True) + + def test_stamp(self): + self.mock_object(migration, 'stamp') + self.db_commands.stamp(version='123') + migration.stamp.assert_called_once_with('123') + + def test_version_commands_list(self): + self.mock_object(version, 'version_string', + mock.Mock(return_value='123')) + with mock.patch('sys.stdout', new=StringIO.StringIO()) as fake_out: + self.version_commands.list() + version.version_string.assert_called_once_with() + self.assertEqual('123\n', fake_out.getvalue()) + + def test_version_commands_call(self): + self.mock_object(version, 'version_string', + mock.Mock(return_value='123')) + with mock.patch('sys.stdout', new=StringIO.StringIO()) as fake_out: + self.version_commands() + version.version_string.assert_called_once_with() + self.assertEqual('123\n', fake_out.getvalue()) + + def test_get_log_commands_no_errors(self): + with mock.patch('sys.stdout', new=StringIO.StringIO()) as fake_out: + CONF.set_override('log_dir', None) + expected_out = 'No errors in logfiles!\n' + + self.get_log_cmds.errors() + + self.assertEqual(expected_out, fake_out.getvalue()) + + @mock.patch('__builtin__.open') + @mock.patch('os.listdir') + def test_get_log_commands_errors(self, listdir, open): + CONF.set_override('log_dir', 'fake-dir') + listdir.return_value = ['fake-error.log'] + + with mock.patch('sys.stdout', new=StringIO.StringIO()) as fake_out: + open.return_value = StringIO.StringIO( + '[ ERROR ] fake-error-message') + expected_out = ('fake-dir/fake-error.log:-\n' + 'Line 1 : [ ERROR ] fake-error-message\n') + self.get_log_cmds.errors() + + self.assertEqual(expected_out, fake_out.getvalue()) + open.assert_called_once_with('fake-dir/fake-error.log', 'r') + listdir.assert_called_once_with(CONF.log_dir) + + @mock.patch('__builtin__.open') + @mock.patch('os.path.exists') + def test_get_log_commands_syslog_no_log_file(self, path_exists, open): + path_exists.return_value = False + exit = self.assertRaises(SystemExit, self.get_log_cmds.syslog) + self.assertEqual(exit.code, 1) + path_exists.assert_any_call('/var/log/syslog') + path_exists.assert_any_call('/var/log/messages') + + @mock.patch('manila.utils.service_is_up') + @mock.patch('manila.db.service_get_all') + @mock.patch('manila.context.get_admin_context') + def test_service_commands_list(self, get_admin_context, service_get_all, + service_is_up): + ctxt = context.RequestContext('fake-user', 'fake-project') + get_admin_context.return_value = ctxt + service = {'binary': 'manila-binary', + 'host': 'fake-host.fake-domain', + 'availability_zone': 'fake-zone', + 'updated_at': '2014-06-30 11:22:33', + 'disabled': False} + service_get_all.return_value = [service] + service_is_up.return_value = True + with mock.patch('sys.stdout', new=StringIO.StringIO()) as fake_out: + format = "%-16s %-36s %-16s %-10s %-5s %-10s" + print_format = format % ('Binary', + 'Host', + 'Zone', + 'Status', + 'State', + 'Updated At') + service_format = format % (service['binary'], + service['host'].partition('.')[0], + service['availability_zone'], + 'enabled', + ':-)', + service['updated_at']) + expected_out = print_format + '\n' + service_format + '\n' + self.service_cmds.list() + self.assertEqual(expected_out, fake_out.getvalue()) + get_admin_context.assert_called_with() + service_get_all.assert_called_with(ctxt) + service_is_up.assert_called_with(service) + + def test_methods_of(self): + obj = type('Fake', (object,), + {name: lambda: 'fake_' for name in ('_a', 'b', 'c')}) + expected = [('b', obj.b), ('c', obj.c)] + self.assertEqual(expected, manila_manage.methods_of(obj)) + + @mock.patch('oslo_config.cfg.ConfigOpts.register_cli_opt') + def test_main_argv_lt_2(self, register_cli_opt): + script_name = 'manila-manage' + sys.argv = [script_name] + CONF(sys.argv[1:], project='manila', version=version.version_string()) + exit = self.assertRaises(SystemExit, manila_manage.main) + + self.assertTrue(register_cli_opt.called) + self.assertEqual(exit.code, 2) + + @mock.patch('oslo_config.cfg.ConfigOpts.__call__') + @mock.patch('manila.openstack.common.log.setup') + @mock.patch('oslo_config.cfg.ConfigOpts.register_cli_opt') + def test_main_sudo_failed(self, register_cli_opt, log_setup, + config_opts_call): + script_name = 'manila-manage' + sys.argv = [script_name, 'fake_category', 'fake_action'] + config_opts_call.side_effect = cfg.ConfigFilesNotFoundError( + mock.sentinel._namespace) + + exit = self.assertRaises(SystemExit, manila_manage.main) + + self.assertTrue(register_cli_opt.called) + config_opts_call.assert_called_once_with( + sys.argv[1:], project='manila', + version=version.version_string()) + self.assertFalse(log_setup.called) + self.assertEqual(exit.code, 2) + + @mock.patch('oslo_config.cfg.ConfigOpts.__call__') + @mock.patch('oslo_config.cfg.ConfigOpts.register_cli_opt') + def test_main(self, register_cli_opt, config_opts_call): + script_name = 'manila-manage' + sys.argv = [script_name, 'config', 'list'] + action_fn = mock.MagicMock() + CONF.category = mock.MagicMock(action_fn=action_fn) + + manila_manage.main() + + self.assertTrue(register_cli_opt.called) + config_opts_call.assert_called_once_with( + sys.argv[1:], project='manila', version=version.version_string()) + self.assertTrue(action_fn.called) + + @ddt.data('bar', '-bar', '--bar') + def test_get_arg_string(self, arg): + parsed_arg = manila_manage.get_arg_string(arg) + self.assertEqual('bar', parsed_arg) diff --git a/manila/tests/cmd/test_scheduler.py b/manila/tests/cmd/test_scheduler.py new file mode 100644 index 0000000000..043fb617b5 --- /dev/null +++ b/manila/tests/cmd/test_scheduler.py @@ -0,0 +1,45 @@ +# Copyright 2015 Mirantis Inc. +# All Rights Reserved. +# +# 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 sys + +from manila.cmd import scheduler as manila_scheduler +from manila import test +from manila import version + +CONF = manila_scheduler.CONF + + +class ManilaCmdSchedulerTestCase(test.TestCase): + + def test_main(self): + sys.argv = ['manila-scheduler'] + self.mock_object(manila_scheduler.log, 'setup') + self.mock_object(manila_scheduler.utils, 'monkey_patch') + self.mock_object(manila_scheduler.service.Service, 'create') + self.mock_object(manila_scheduler.service, 'serve') + self.mock_object(manila_scheduler.service, 'wait') + + manila_scheduler.main() + + self.assertEqual(CONF.project, 'manila') + self.assertEqual(CONF.version, version.version_string()) + manila_scheduler.log.setup.assert_called_once_with(CONF, "manila") + manila_scheduler.utils.monkey_patch.assert_called_once_with() + manila_scheduler.service.Service.create.assert_called_once_with( + binary='manila-scheduler') + manila_scheduler.service.wait.assert_called_once_with() + manila_scheduler.service.serve.assert_called_once_with( + manila_scheduler.service.Service.create.return_value) diff --git a/manila/tests/cmd/test_share.py b/manila/tests/cmd/test_share.py new file mode 100644 index 0000000000..aff403bc7b --- /dev/null +++ b/manila/tests/cmd/test_share.py @@ -0,0 +1,64 @@ +# Copyright 2015 Mirantis Inc. +# All Rights Reserved. +# +# 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 sys + +import ddt +import mock + +from manila.cmd import share as manila_share +from manila import test + +CONF = manila_share.CONF + + +@ddt.ddt +class ManilaCmdShareTestCase(test.TestCase): + + @ddt.data(None, [], ['foo', ], ['foo', 'bar', ]) + def test_main(self, backends): + self.mock_object(manila_share.log, 'setup') + self.mock_object(manila_share.utils, 'monkey_patch') + self.mock_object(manila_share.service, 'ProcessLauncher') + self.mock_object(manila_share.service.Service, 'create') + self.launcher = manila_share.service.ProcessLauncher.return_value + self.mock_object(self.launcher, 'launch_server') + self.mock_object(self.launcher, 'wait') + self.server = manila_share.service.Service.create.return_value + fake_host = 'fake_host' + CONF.set_override('enabled_share_backends', backends) + CONF.set_override('host', fake_host) + sys.argv = ['manila-share'] + + manila_share.main() + + manila_share.log.setup.assert_called_once_with(CONF, "manila") + manila_share.utils.monkey_patch.assert_called_once_with() + manila_share.service.ProcessLauncher.assert_called_once_with() + self.launcher.wait.assert_called_once_with() + + if backends: + manila_share.service.Service.create.assert_has_calls([ + mock.call( + host=fake_host + '@' + backend, + service_name=backend, + binary='manila-share') for backend in backends + ]) + self.launcher.launch_server.assert_has_calls([ + mock.call(self.server) for backend in backends]) + else: + manila_share.service.Service.create.assert_called_once_with( + binary='manila-share') + self.launcher.launch_server.assert_called_once_with(self.server) diff --git a/setup.cfg b/setup.cfg index 4ab7daf219..f6571df706 100644 --- a/setup.cfg +++ b/setup.cfg @@ -24,16 +24,14 @@ setup-hooks = [files] packages = manila -scripts = - bin/manila-all - bin/manila-api - bin/manila-manage - bin/manila-scheduler - bin/manila-share - [entry_points] console_scripts = + manila-all = manila.cmd.all:main + manila-api = manila.cmd.api:main + manila-manage = manila.cmd.manage:main manila-rootwrap = oslo.rootwrap.cmd:main + manila-scheduler = manila.cmd.scheduler:main + manila-share = manila.cmd.share:main manila.scheduler.filters = AvailabilityZoneFilter = manila.openstack.common.scheduler.filters.availability_zone_filter:AvailabilityZoneFilter CapabilitiesFilter = manila.openstack.common.scheduler.filters.capabilities_filter:CapabilitiesFilter diff --git a/tox.ini b/tox.ini index 8901d3187a..bc2e922c26 100644 --- a/tox.ini +++ b/tox.ini @@ -17,7 +17,6 @@ downloadcache = ~/cache/pip [testenv:pep8] commands = flake8 {posargs} - flake8 --filename=manila* bin # Run bashate during pep8 runs to ensure violations are caught by # the check and gate queues. bashate tools/enable-pre-commit-hook.sh \