Add a placement-manage CLI
This change adds a rudimentary command line tool, 'placement-manage' that can do three things: * placement-manage --version: report the current version of the software * placement-manage db sync: sync the db to the 'head' alembic version * placement-manage db version: report the current version of the db It is written following the examples set by both nova and ironic for using oslo config driven command line parsing. It is not as full featured as the nova version (with decorators for argument handling and help text etc) because we don't need that yet. There's plenty of room for improvement, but the intention here is to keep things simple until we need them to be otherwise. The provided unit tests cover that the arg parsing behaves as expected and that the right commands are connected the right args. The actual functionality of the 'db sync' command (a migration.upgrade) is tested in runs that use devstack as well as the test_migrations functional test. Errors during the migration simply raise exceptions which will output noisily to the console. At this stage this is desirable and suitable. A new doc for the cli is added, with basic information for placement-manage. Note that at this time the deployment documentation has not been updated. That will be done in a later change. Future changes may include (if we can't avoid it) tools for initiating online migrations from the command line. Needed-By: https://review.openstack.org/600162/ Change-Id: I1ff472106610150a587f5286f26a6bd7c1aa84f4
This commit is contained in:
parent
f63b14c6a4
commit
7b5218d8e3
25
doc/source/cli/index.rst
Normal file
25
doc/source/cli/index.rst
Normal file
@ -0,0 +1,25 @@
|
||||
..
|
||||
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.
|
||||
|
||||
Command-line Utilities
|
||||
======================
|
||||
|
||||
In this section you will find information on placement's command line
|
||||
utilities:
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
placement-manage
|
||||
|
67
doc/source/cli/placement-manage.rst
Normal file
67
doc/source/cli/placement-manage.rst
Normal file
@ -0,0 +1,67 @@
|
||||
..
|
||||
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.
|
||||
|
||||
================
|
||||
placement-manage
|
||||
================
|
||||
|
||||
|
||||
Synopsis
|
||||
========
|
||||
|
||||
::
|
||||
|
||||
placement-manage <category> <action>
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
:program:`placement-manage` is used to perform administrative tasks with the
|
||||
placement service. It is designed for use by operators and deployers.
|
||||
|
||||
Options
|
||||
=======
|
||||
|
||||
The standard pattern for executing a ``placement-manage`` command is::
|
||||
|
||||
placement-manage [-h] [--config-dir DIR] [--config-file PATH]
|
||||
<category> <command> [<args>]
|
||||
|
||||
Run without arguments to see a list of available command categories::
|
||||
|
||||
placement-manage
|
||||
|
||||
You can also run with a category argument such as ``db`` to see a list of all
|
||||
commands in that category::
|
||||
|
||||
placement-manage db
|
||||
|
||||
Configuration options (for example the ``[placement_database]/connection``
|
||||
URL) are by default found in a file at ``/etc/placement/placement.conf``. The
|
||||
``config-dir`` and ``config-file`` arguments may be used to select a different
|
||||
file.
|
||||
|
||||
The following sections describe the available categories and arguments for
|
||||
placement-manage.
|
||||
|
||||
Placement Database
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``placement-manage db version``
|
||||
Print the current database version.
|
||||
|
||||
``placement-manage db sync``
|
||||
Upgrade the database schema to the most recent version. The local database
|
||||
connection is determined by ``[placement_database]/connection`` in the
|
||||
configuration file used by placement-manage. If the ``connection`` option
|
||||
is not set, the command will fail. The defined database must already exist.
|
@ -42,12 +42,15 @@ example, available disk may be solid state drives (SSD).
|
||||
References
|
||||
~~~~~~~~~~
|
||||
|
||||
For an overview of some of the features provided by placement, see
|
||||
:doc:`Placement Usage <usage/index>`.
|
||||
|
||||
For a command line reference, see :doc:`cli/index`.
|
||||
|
||||
The following specifications represent the stages of design and development of
|
||||
resource providers and the Placement service. Implementation details may have
|
||||
changed or be partially complete at this time.
|
||||
|
||||
For an overview of some of the features, see the
|
||||
:doc:`Placement Usage <usage/index>`.
|
||||
|
||||
* `Generic Resource Pools <https://specs.openstack.org/openstack/nova-specs/specs/newton/implemented/generic-resource-pools.html>`_
|
||||
* `Compute Node Inventory <https://specs.openstack.org/openstack/nova-specs/specs/newton/implemented/compute-node-inventory-newton.html>`_
|
||||
@ -356,6 +359,7 @@ contribute to the placement project.
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
cli/index
|
||||
configuration/index
|
||||
contributor/index
|
||||
contributor/api-ref-guideline
|
||||
|
0
placement/cmd/__init__.py
Normal file
0
placement/cmd/__init__.py
Normal file
84
placement/cmd/manage.py
Normal file
84
placement/cmd/manage.py
Normal file
@ -0,0 +1,84 @@
|
||||
# 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 oslo_config import cfg
|
||||
import pbr.version
|
||||
|
||||
from placement import conf
|
||||
from placement.db.sqlalchemy import migration
|
||||
from placement import db_api
|
||||
from placement.i18n import _
|
||||
|
||||
version_info = pbr.version.VersionInfo('openstack-placement')
|
||||
|
||||
|
||||
class DbCommands(object):
|
||||
|
||||
def db_sync(self):
|
||||
# Let exceptions raise for now, they will go to stderr.
|
||||
migration.upgrade('head')
|
||||
return 0
|
||||
|
||||
def db_version(self):
|
||||
print(migration.version())
|
||||
return 0
|
||||
|
||||
|
||||
def add_db_command_parsers(subparsers):
|
||||
command_object = DbCommands()
|
||||
|
||||
# If we set False here, we avoid having an exit during the parse
|
||||
# args part of CONF processing and we can thus print out meaningful
|
||||
# help text.
|
||||
subparsers.required = False
|
||||
parser = subparsers.add_parser('db')
|
||||
parser.set_defaults(func=parser.print_help)
|
||||
db_parser = parser.add_subparsers(description='database commands')
|
||||
|
||||
help = _('Sync the datatabse to the current version.')
|
||||
sync_parser = db_parser.add_parser('sync', help=help, description=help)
|
||||
sync_parser.set_defaults(func=command_object.db_sync)
|
||||
|
||||
help = _('Report the current database version.')
|
||||
version_parser = db_parser.add_parser(
|
||||
'version', help=help, description=help)
|
||||
version_parser.set_defaults(func=command_object.db_version)
|
||||
|
||||
|
||||
def setup_commands():
|
||||
# This is a separate method because it facilitates unit testing.
|
||||
# Use an additional SubCommandOpt and parser for each new sub command.
|
||||
command_opt = cfg.SubCommandOpt(
|
||||
'db', dest='command', title='Command', help=_('Available DB commands'),
|
||||
handler=add_db_command_parsers)
|
||||
return [command_opt]
|
||||
|
||||
|
||||
def main():
|
||||
CONF = conf.CONF
|
||||
command_opts = setup_commands()
|
||||
CONF.register_cli_opts(command_opts)
|
||||
CONF(sys.argv[1:], project='placement',
|
||||
version=version_info.version_string(),
|
||||
default_config_files=None)
|
||||
db_api.configure(CONF)
|
||||
|
||||
try:
|
||||
func = CONF.command.func
|
||||
return_code = func()
|
||||
# If return_code ends up None we assume 0.
|
||||
sys.exit(return_code or 0)
|
||||
except cfg.NoSuchOptError:
|
||||
CONF.print_help()
|
||||
sys.exit(1)
|
0
placement/tests/unit/cmd/__init__.py
Normal file
0
placement/tests/unit/cmd/__init__.py
Normal file
81
placement/tests/unit/cmd/test_manage.py
Normal file
81
placement/tests/unit/cmd/test_manage.py
Normal file
@ -0,0 +1,81 @@
|
||||
# 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 mock
|
||||
from oslo_config import cfg
|
||||
from oslo_config import fixture as config_fixture
|
||||
from oslotest import output
|
||||
import six
|
||||
import testtools
|
||||
|
||||
from placement.cmd import manage
|
||||
|
||||
|
||||
class TestCommandParsers(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestCommandParsers, self).setUp()
|
||||
self.conf = cfg.CONF
|
||||
conf_fixture = config_fixture.Config(self.conf)
|
||||
self.useFixture(conf_fixture)
|
||||
# Quiet output from argparse (used within oslo_config).
|
||||
# If you are debugging, commenting this out might be useful.
|
||||
self.useFixture(output.CaptureOutput(do_stderr=True))
|
||||
# We don't use a database, but we need to set the opt as
|
||||
# it's required for a valid config.
|
||||
conf_fixture.config(group="placement_database", connection='sqlite://')
|
||||
command_opts = manage.setup_commands()
|
||||
# Command line opts must be registered on the conf_fixture, otherwise
|
||||
# they carry over globally.
|
||||
conf_fixture.register_cli_opts(command_opts)
|
||||
|
||||
def test_commands_associated(self):
|
||||
"""Test that commands get parsed as desired.
|
||||
|
||||
This leaves out --version, which is built into oslo.config's handling.
|
||||
"""
|
||||
for command, args in [
|
||||
('db_version', ['db', 'version']),
|
||||
('db_sync', ['db', 'sync']),
|
||||
]:
|
||||
with mock.patch('placement.cmd.manage.DbCommands.'
|
||||
+ command) as mock_command:
|
||||
self.conf(args, default_config_files=[])
|
||||
self.conf.command.func()
|
||||
mock_command.assert_called_once_with()
|
||||
|
||||
def test_non_command(self):
|
||||
"""A non-existent command should fail."""
|
||||
self.assertRaises(SystemExit,
|
||||
self.conf, ['pony'], default_config_files=[])
|
||||
|
||||
def test_empty_command(self):
|
||||
"""An empty command should create no func."""
|
||||
# Python 2.7 and 3.x behave differently here, but the result is
|
||||
# satisfactory. Both result in some help output, but the Python 3
|
||||
# help is better.
|
||||
def parse_conf():
|
||||
self.conf([], default_config_files=[])
|
||||
|
||||
def get_func():
|
||||
return self.conf.command.func
|
||||
|
||||
if six.PY2:
|
||||
self.assertRaises(SystemExit, parse_conf)
|
||||
else:
|
||||
parse_conf()
|
||||
self.assertRaises(cfg.NoSuchOptError, get_func)
|
||||
|
||||
def test_too_many_args(self):
|
||||
self.assertRaises(SystemExit,
|
||||
self.conf, ['version', '5'], default_config_files=[])
|
@ -41,10 +41,8 @@ oslo.policy.policies =
|
||||
placement = placement.policies:list_rules
|
||||
|
||||
console_scripts =
|
||||
# TODO(cdent): We will need some kind of placement-manage and
|
||||
# placement-status, eventually
|
||||
# nova-manage = nova.cmd.manage:main
|
||||
# nova-status = nova.cmd.status:main
|
||||
# TODO(cdent): We will need some kind of placement-status, eventually
|
||||
placement-manage = placement.cmd.manage:main
|
||||
wsgi_scripts =
|
||||
placement-api = placement.wsgi:init_application
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user