diff --git a/novaclient/shell.py b/novaclient/shell.py index a43c02f84..18d83aa06 100644 --- a/novaclient/shell.py +++ b/novaclient/shell.py @@ -29,6 +29,7 @@ from keystoneauth1 import loading from oslo_utils import encodeutils from oslo_utils import importutils from oslo_utils import strutils +import six HAS_KEYRING = False all_errors = ValueError @@ -63,6 +64,153 @@ HINT_HELP_MSG = (" [hint: use '--os-compute-api-version' flag to show help " logger = logging.getLogger(__name__) +class DeprecatedAction(argparse.Action): + """An argparse action for deprecated options. + + This class is an ``argparse.Action`` subclass that allows command + line options to be explicitly deprecated. It modifies the help + text for the option to indicate that it's deprecated (unless help + has been suppressed using ``argparse.SUPPRESS``), and provides a + means to specify an alternate option to use using the ``use`` + keyword argument to ``argparse.ArgumentParser.add_argument()``. + The original action may be specified with the ``real_action`` + keyword argument, which has the same interpretation as the + ``action`` argument to ``argparse.ArgumentParser.add_argument()``, + with the addition of the special "nothing" action which completely + ignores the option (other than emitting the deprecation warning). + Note that the deprecation warning is only emitted once per + specific option string. + + Note: If the ``real_action`` keyword argument specifies an unknown + action, no warning will be emitted unless the action is used, due + to limitations with the method used to resolve the action names. + """ + + def __init__(self, option_strings, dest, help=None, + real_action=None, use=None, **kwargs): + """Initialize a ``DeprecatedAction`` instance. + + :param option_strings: The recognized option strings. + :param dest: The attribute that will be set. + :param help: Help text. This will be updated to indicate the + deprecation, and if ``use`` is provided, that + text will be included as well. + :param real_action: The actual action to invoke. This is + interpreted the same way as the ``action`` + parameter. + :param use: Text explaining which option to use instead. + """ + + # Update the help text + if not help: + if use: + help = _('Deprecated; %(use)s') % {'use': use} + else: + help = _('Deprecated') + elif help != argparse.SUPPRESS: + if use: + help = _('%(help)s (Deprecated; %(use)s)') % { + 'help': help, + 'use': use, + } + else: + help = _('%(help)s (Deprecated)') % {'help': help} + + # Initialize ourself appropriately + super(DeprecatedAction, self).__init__( + option_strings, dest, help=help, **kwargs) + + # 'emitted' tracks which warnings we've emitted + self.emitted = set() + self.use = use + + # Select the appropriate action + if real_action == 'nothing': + # NOTE(Vek): "nothing" is distinct from a real_action=None + # argument. When real_action=None, the argparse default + # action of "store" is used; when real_action='nothing', + # however, we explicitly inhibit doing anything with the + # option + self.real_action_args = False + self.real_action = None + elif real_action is None or isinstance(real_action, six.string_types): + # Specified by string (or None); we have to have a parser + # to look up the actual action, so defer to later + self.real_action_args = (option_strings, dest, help, kwargs) + self.real_action = real_action + else: + self.real_action_args = False + self.real_action = real_action( + option_strings, dest, help=help, **kwargs) + + def _get_action(self, parser): + """Retrieve the action callable. + + This internal method is used to retrieve the callable + implementing the action. If ``real_action`` was specified as + ``None`` or one of the standard string names, an internal + method of the ``argparse.ArgumentParser`` instance is used to + resolve it into an actual action class, which is then + instantiated. This is cached, in case the action is called + multiple times. + + :param parser: The ``argparse.ArgumentParser`` instance. + + :returns: The action callable. + """ + + # If a lookup is needed, look up the action in the parser + if self.real_action_args is not False: + option_strings, dest, help, kwargs = self.real_action_args + action_class = parser._registry_get('action', self.real_action) + + # Did we find the action class? + if action_class is None: + print(_('WARNING: Programming error: Unknown real action ' + '"%s"') % self.real_action, file=sys.stderr) + self.real_action = None + else: + # OK, instantiate the action class + self.real_action = action_class( + option_strings, dest, help=help, **kwargs) + + # It's been resolved, no further need to look it up + self.real_action_args = False + + return self.real_action + + def __call__(self, parser, namespace, values, option_string): + """Implement the action. + + Emits the deprecation warning message (only once for any given + option string), then calls the real action (if any). + + :param parser: The ``argparse.ArgumentParser`` instance. + :param namespace: The ``argparse.Namespace`` object which + should have an attribute set. + :param values: Any arguments provided to the option. + :param option_string: The option string that was used. + """ + + action = self._get_action(parser) + + # Only emit the deprecation warning once per option + if option_string not in self.emitted: + if self.use: + print(_('WARNING: Option "%(option)s" is deprecated; ' + '%(use)s') % { + 'option': option_string, + 'use': self.use, + }, file=sys.stderr) + else: + print(_('WARNING: Option "%(option)s" is deprecated') % + {'option': option_string}, file=sys.stderr) + self.emitted.add(option_string) + + if action: + action(parser, namespace, values, option_string) + + def positive_non_zero_float(text): if text is None: return None @@ -313,24 +461,32 @@ class OpenStackComputeShell(object): action='store_true', help=_("Print call timing info.")) - parser.add_argument( - '--os-auth-token', - help=argparse.SUPPRESS) - parser.add_argument( '--os_username', + action=DeprecatedAction, + use=_('use "%s"; this option will be removed ' + 'in novaclient 3.3.0.') % '--os-username', help=argparse.SUPPRESS) parser.add_argument( '--os_password', + action=DeprecatedAction, + use=_('use "%s"; this option will be removed ' + 'in novaclient 3.3.0.') % '--os-password', help=argparse.SUPPRESS) parser.add_argument( '--os_tenant_name', + action=DeprecatedAction, + use=_('use "%s"; this option will be removed ' + 'in novaclient 3.3.0.') % '--os-tenant-name', help=argparse.SUPPRESS) parser.add_argument( '--os_auth_url', + action=DeprecatedAction, + use=_('use "%s"; this option will be removed ' + 'in novaclient 3.3.0.') % '--os-auth-url', help=argparse.SUPPRESS) parser.add_argument( @@ -340,6 +496,9 @@ class OpenStackComputeShell(object): help=_('Defaults to env[OS_REGION_NAME].')) parser.add_argument( '--os_region_name', + action=DeprecatedAction, + use=_('use "%s"; this option will be removed ' + 'in novaclient 3.3.0.') % '--os-region-name', help=argparse.SUPPRESS) parser.add_argument( @@ -349,6 +508,9 @@ class OpenStackComputeShell(object): help=argparse.SUPPRESS) parser.add_argument( '--os_auth_system', + action=DeprecatedAction, + use=_('use "%s"; this option will be removed ' + 'in novaclient 3.3.0.') % '--os-auth-system', help=argparse.SUPPRESS) parser.add_argument( @@ -357,6 +519,9 @@ class OpenStackComputeShell(object): help=_('Defaults to compute for most actions.')) parser.add_argument( '--service_type', + action=DeprecatedAction, + use=_('use "%s"; this option will be removed ' + 'in novaclient 3.3.0.') % '--service-type', help=argparse.SUPPRESS) parser.add_argument( @@ -366,6 +531,9 @@ class OpenStackComputeShell(object): help=_('Defaults to env[NOVA_SERVICE_NAME].')) parser.add_argument( '--service_name', + action=DeprecatedAction, + use=_('use "%s"; this option will be removed ' + 'in novaclient 3.3.0.') % '--service-name', help=argparse.SUPPRESS) parser.add_argument( @@ -375,6 +543,9 @@ class OpenStackComputeShell(object): help=_('Defaults to env[NOVA_VOLUME_SERVICE_NAME].')) parser.add_argument( '--volume_service_name', + action=DeprecatedAction, + use=_('use "%s"; this option will be removed ' + 'in novaclient 3.3.0.') % '--volume-service-name', help=argparse.SUPPRESS) parser.add_argument( @@ -391,6 +562,9 @@ class OpenStackComputeShell(object): parser.add_argument( '--endpoint-type', + action=DeprecatedAction, + use=_('use "%s"; this option will be removed ' + 'in novaclient 3.3.0.') % '--os-endpoint-type', help=argparse.SUPPRESS) # NOTE(dtroyer): We can't add --endpoint_type here due to argparse # thinking usage-list --end is ambiguous; but it @@ -408,6 +582,9 @@ class OpenStackComputeShell(object): '"X.latest", defaults to env[OS_COMPUTE_API_VERSION].')) parser.add_argument( '--os_compute_api_version', + action=DeprecatedAction, + use=_('use "%s"; this option will be removed ' + 'in novaclient 3.3.0.') % '--os-compute-api-version', help=argparse.SUPPRESS) parser.add_argument( @@ -417,8 +594,12 @@ class OpenStackComputeShell(object): default=utils.env('NOVACLIENT_BYPASS_URL'), help="Use this API endpoint instead of the Service Catalog. " "Defaults to env[NOVACLIENT_BYPASS_URL].") - parser.add_argument('--bypass_url', - help=argparse.SUPPRESS) + parser.add_argument( + '--bypass_url', + action=DeprecatedAction, + use=_('use "%s"; this option will be removed ' + 'in novaclient 3.3.0.') % '--bypass-url', + help=argparse.SUPPRESS) # The auth-system-plugins might require some extra options novaclient.auth_plugin.load_auth_system_opts(parser) @@ -544,10 +725,18 @@ class OpenStackComputeShell(object): if '--endpoint_type' in argv: spot = argv.index('--endpoint_type') argv[spot] = '--endpoint-type' + # NOTE(Vek): Not emitting a warning here, as that will + # occur when "--endpoint-type" is processed + # For backwards compat with old os-auth-token parameter if '--os-auth-token' in argv: spot = argv.index('--os-auth-token') argv[spot] = '--os-token' + print(_('WARNING: Option "%(option)s" is deprecated; %(use)s') % { + 'option': '--os-auth-token', + 'use': _('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--os-token', + }, file=sys.stderr) (args, args_list) = parser.parse_known_args(argv) diff --git a/novaclient/tests/unit/test_shell.py b/novaclient/tests/unit/test_shell.py index 82559cf24..38f569546 100644 --- a/novaclient/tests/unit/test_shell.py +++ b/novaclient/tests/unit/test_shell.py @@ -11,6 +11,7 @@ # License for the specific language governing permissions and limitations # under the License. +import argparse import distutils.version as dist_version import re import sys @@ -76,6 +77,261 @@ def _create_ver_list(versions): return {'versions': {'values': versions}} +class DeprecatedActionTest(utils.TestCase): + @mock.patch.object(argparse.Action, '__init__', return_value=None) + def test_init_emptyhelp_nouse(self, mock_init): + result = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', a=1, b=2, c=3) + + self.assertEqual(result.emitted, set()) + self.assertEqual(result.use, None) + self.assertEqual(result.real_action_args, + ('option_strings', 'dest', 'Deprecated', + {'a': 1, 'b': 2, 'c': 3})) + self.assertEqual(result.real_action, None) + mock_init.assert_called_once_with( + 'option_strings', 'dest', help='Deprecated', a=1, b=2, c=3) + + @mock.patch.object(novaclient.shell.argparse.Action, '__init__', + return_value=None) + def test_init_emptyhelp_withuse(self, mock_init): + result = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', use='use this instead', a=1, b=2, c=3) + + self.assertEqual(result.emitted, set()) + self.assertEqual(result.use, 'use this instead') + self.assertEqual(result.real_action_args, + ('option_strings', 'dest', + 'Deprecated; use this instead', + {'a': 1, 'b': 2, 'c': 3})) + self.assertEqual(result.real_action, None) + mock_init.assert_called_once_with( + 'option_strings', 'dest', help='Deprecated; use this instead', + a=1, b=2, c=3) + + @mock.patch.object(argparse.Action, '__init__', return_value=None) + def test_init_withhelp_nouse(self, mock_init): + result = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', help='some help', a=1, b=2, c=3) + + self.assertEqual(result.emitted, set()) + self.assertEqual(result.use, None) + self.assertEqual(result.real_action_args, + ('option_strings', 'dest', + 'some help (Deprecated)', + {'a': 1, 'b': 2, 'c': 3})) + self.assertEqual(result.real_action, None) + mock_init.assert_called_once_with( + 'option_strings', 'dest', help='some help (Deprecated)', + a=1, b=2, c=3) + + @mock.patch.object(novaclient.shell.argparse.Action, '__init__', + return_value=None) + def test_init_withhelp_withuse(self, mock_init): + result = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', help='some help', + use='use this instead', a=1, b=2, c=3) + + self.assertEqual(result.emitted, set()) + self.assertEqual(result.use, 'use this instead') + self.assertEqual(result.real_action_args, + ('option_strings', 'dest', + 'some help (Deprecated; use this instead)', + {'a': 1, 'b': 2, 'c': 3})) + self.assertEqual(result.real_action, None) + mock_init.assert_called_once_with( + 'option_strings', 'dest', + help='some help (Deprecated; use this instead)', + a=1, b=2, c=3) + + @mock.patch.object(argparse.Action, '__init__', return_value=None) + def test_init_suppresshelp_nouse(self, mock_init): + result = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', help=argparse.SUPPRESS, a=1, b=2, c=3) + + self.assertEqual(result.emitted, set()) + self.assertEqual(result.use, None) + self.assertEqual(result.real_action_args, + ('option_strings', 'dest', argparse.SUPPRESS, + {'a': 1, 'b': 2, 'c': 3})) + self.assertEqual(result.real_action, None) + mock_init.assert_called_once_with( + 'option_strings', 'dest', help=argparse.SUPPRESS, a=1, b=2, c=3) + + @mock.patch.object(novaclient.shell.argparse.Action, '__init__', + return_value=None) + def test_init_suppresshelp_withuse(self, mock_init): + result = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', help=argparse.SUPPRESS, + use='use this instead', a=1, b=2, c=3) + + self.assertEqual(result.emitted, set()) + self.assertEqual(result.use, 'use this instead') + self.assertEqual(result.real_action_args, + ('option_strings', 'dest', argparse.SUPPRESS, + {'a': 1, 'b': 2, 'c': 3})) + self.assertEqual(result.real_action, None) + mock_init.assert_called_once_with( + 'option_strings', 'dest', help=argparse.SUPPRESS, a=1, b=2, c=3) + + @mock.patch.object(argparse.Action, '__init__', return_value=None) + def test_init_action_nothing(self, mock_init): + result = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', real_action='nothing', a=1, b=2, c=3) + + self.assertEqual(result.emitted, set()) + self.assertEqual(result.use, None) + self.assertEqual(result.real_action_args, False) + self.assertEqual(result.real_action, None) + mock_init.assert_called_once_with( + 'option_strings', 'dest', help='Deprecated', a=1, b=2, c=3) + + @mock.patch.object(argparse.Action, '__init__', return_value=None) + def test_init_action_string(self, mock_init): + result = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', real_action='store', a=1, b=2, c=3) + + self.assertEqual(result.emitted, set()) + self.assertEqual(result.use, None) + self.assertEqual(result.real_action_args, + ('option_strings', 'dest', 'Deprecated', + {'a': 1, 'b': 2, 'c': 3})) + self.assertEqual(result.real_action, 'store') + mock_init.assert_called_once_with( + 'option_strings', 'dest', help='Deprecated', a=1, b=2, c=3) + + @mock.patch.object(argparse.Action, '__init__', return_value=None) + def test_init_action_other(self, mock_init): + action = mock.Mock() + result = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', real_action=action, a=1, b=2, c=3) + + self.assertEqual(result.emitted, set()) + self.assertEqual(result.use, None) + self.assertEqual(result.real_action_args, False) + self.assertEqual(result.real_action, action.return_value) + mock_init.assert_called_once_with( + 'option_strings', 'dest', help='Deprecated', a=1, b=2, c=3) + action.assert_called_once_with( + 'option_strings', 'dest', help='Deprecated', a=1, b=2, c=3) + + @mock.patch.object(sys, 'stderr', six.StringIO()) + def test_get_action_nolookup(self): + action_class = mock.Mock() + parser = mock.Mock(**{ + '_registry_get.return_value': action_class, + }) + obj = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', real_action='nothing', const=1) + obj.real_action = 'action' + + result = obj._get_action(parser) + + self.assertEqual(result, 'action') + self.assertEqual(obj.real_action, 'action') + self.assertFalse(parser._registry_get.called) + self.assertFalse(action_class.called) + self.assertEqual(sys.stderr.getvalue(), '') + + @mock.patch.object(sys, 'stderr', six.StringIO()) + def test_get_action_lookup_noresult(self): + parser = mock.Mock(**{ + '_registry_get.return_value': None, + }) + obj = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', real_action='store', const=1) + + result = obj._get_action(parser) + + self.assertEqual(result, None) + self.assertEqual(obj.real_action, None) + parser._registry_get.assert_called_once_with( + 'action', 'store') + self.assertEqual(sys.stderr.getvalue(), + 'WARNING: Programming error: Unknown real action ' + '"store"\n') + + @mock.patch.object(sys, 'stderr', six.StringIO()) + def test_get_action_lookup_withresult(self): + action_class = mock.Mock() + parser = mock.Mock(**{ + '_registry_get.return_value': action_class, + }) + obj = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', real_action='store', const=1) + + result = obj._get_action(parser) + + self.assertEqual(result, action_class.return_value) + self.assertEqual(obj.real_action, action_class.return_value) + parser._registry_get.assert_called_once_with( + 'action', 'store') + action_class.assert_called_once_with( + 'option_strings', 'dest', help='Deprecated', const=1) + self.assertEqual(sys.stderr.getvalue(), '') + + @mock.patch.object(sys, 'stderr', six.StringIO()) + @mock.patch.object(novaclient.shell.DeprecatedAction, '_get_action') + def test_call_unemitted_nouse(self, mock_get_action): + obj = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest') + + obj('parser', 'namespace', 'values', 'option_string') + + self.assertEqual(obj.emitted, set(['option_string'])) + mock_get_action.assert_called_once_with('parser') + mock_get_action.return_value.assert_called_once_with( + 'parser', 'namespace', 'values', 'option_string') + self.assertEqual(sys.stderr.getvalue(), + 'WARNING: Option "option_string" is deprecated\n') + + @mock.patch.object(sys, 'stderr', six.StringIO()) + @mock.patch.object(novaclient.shell.DeprecatedAction, '_get_action') + def test_call_unemitted_withuse(self, mock_get_action): + obj = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', use='use this instead') + + obj('parser', 'namespace', 'values', 'option_string') + + self.assertEqual(obj.emitted, set(['option_string'])) + mock_get_action.assert_called_once_with('parser') + mock_get_action.return_value.assert_called_once_with( + 'parser', 'namespace', 'values', 'option_string') + self.assertEqual(sys.stderr.getvalue(), + 'WARNING: Option "option_string" is deprecated; ' + 'use this instead\n') + + @mock.patch.object(sys, 'stderr', six.StringIO()) + @mock.patch.object(novaclient.shell.DeprecatedAction, '_get_action') + def test_call_emitted_nouse(self, mock_get_action): + obj = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest') + obj.emitted.add('option_string') + + obj('parser', 'namespace', 'values', 'option_string') + + self.assertEqual(obj.emitted, set(['option_string'])) + mock_get_action.assert_called_once_with('parser') + mock_get_action.return_value.assert_called_once_with( + 'parser', 'namespace', 'values', 'option_string') + self.assertEqual(sys.stderr.getvalue(), '') + + @mock.patch.object(sys, 'stderr', six.StringIO()) + @mock.patch.object(novaclient.shell.DeprecatedAction, '_get_action') + def test_call_emitted_withuse(self, mock_get_action): + obj = novaclient.shell.DeprecatedAction( + 'option_strings', 'dest', use='use this instead') + obj.emitted.add('option_string') + + obj('parser', 'namespace', 'values', 'option_string') + + self.assertEqual(obj.emitted, set(['option_string'])) + mock_get_action.assert_called_once_with('parser') + mock_get_action.return_value.assert_called_once_with( + 'parser', 'namespace', 'values', 'option_string') + self.assertEqual(sys.stderr.getvalue(), '') + + class ParserTest(utils.TestCase): def setUp(self): diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py index cbb7f122d..1eb4fc02a 100644 --- a/novaclient/v2/shell.py +++ b/novaclient/v2/shell.py @@ -43,6 +43,7 @@ from novaclient import client from novaclient import exceptions from novaclient.i18n import _ from novaclient.openstack.common import cliutils +from novaclient import shell from novaclient import utils from novaclient.v2 import availability_zones from novaclient.v2 import quotas @@ -376,6 +377,9 @@ def _boot(cs, args): default=None, type=int, metavar='', + action=shell.DeprecatedAction, + use=_('use "--min-count" and "--max-count"; this option will be removed ' + 'in novaclient 3.3.0.'), help=argparse.SUPPRESS) @cliutils.arg( '--min-count', @@ -412,6 +416,9 @@ def _boot(cs, args): the command keypair-add.")) @cliutils.arg( '--key_name', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--key-name', help=argparse.SUPPRESS) @cliutils.arg('name', metavar='', help=_('Name for the new server.')) @cliutils.arg( @@ -421,6 +428,9 @@ def _boot(cs, args): help=_("user data file to pass to be exposed by the metadata server.")) @cliutils.arg( '--user_data', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--user-data', help=argparse.SUPPRESS) @cliutils.arg( '--availability-zone', @@ -429,6 +439,9 @@ def _boot(cs, args): help=_("The availability zone for server placement.")) @cliutils.arg( '--availability_zone', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--availability-zone', help=argparse.SUPPRESS) @cliutils.arg( '--security-groups', @@ -437,6 +450,9 @@ def _boot(cs, args): help=_("Comma separated list of security group names.")) @cliutils.arg( '--security_groups', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--security-groups', help=argparse.SUPPRESS) @cliutils.arg( '--block-device-mapping', @@ -447,7 +463,10 @@ def _boot(cs, args): "=:::.")) @cliutils.arg( '--block_device_mapping', - action='append', + real_action='append', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--block-device-mapping', help=argparse.SUPPRESS) @cliutils.arg( '--block-device', @@ -1288,6 +1307,9 @@ def do_image_delete(cs, args): help=_('Only return servers that match reservation-id.')) @cliutils.arg( '--reservation_id', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--reservation-id', help=argparse.SUPPRESS) @cliutils.arg( '--ip', @@ -1315,6 +1337,9 @@ def do_image_delete(cs, args): help=_('Search with regular expression match by server name.')) @cliutils.arg( '--instance_name', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--instance-name', help=argparse.SUPPRESS) @cliutils.arg( '--status', @@ -1356,6 +1381,9 @@ def do_image_delete(cs, args): nargs='?', type=int, const=1, + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--all-tenants', help=argparse.SUPPRESS) @cliutils.arg( '--tenant', @@ -1561,6 +1589,9 @@ def do_reboot(cs, args): help=_("Set the provided admin password on the rebuilt server.")) @cliutils.arg( '--rebuild_password', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--rebuild-password', help=argparse.SUPPRESS) @cliutils.arg( '--poll', @@ -2132,6 +2163,9 @@ def _translate_volume_attachments_keys(collection): nargs='?', type=int, const=1, + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--all-tenants', help=argparse.SUPPRESS) def do_volume_list(cs, args): """DEPRECATED: List all the volumes.""" @@ -2171,6 +2205,9 @@ def do_volume_show(cs, args): help=_('Optional snapshot ID to create the volume from. (Default=None)')) @cliutils.arg( '--snapshot_id', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--snapshot-id', help=argparse.SUPPRESS) @cliutils.arg( '--image-id', @@ -2184,6 +2221,9 @@ def do_volume_show(cs, args): help=_('Optional volume name. (Default=None)')) @cliutils.arg( '--display_name', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--display-name', help=argparse.SUPPRESS) @cliutils.arg( '--display-description', @@ -2192,6 +2232,9 @@ def do_volume_show(cs, args): help=_('Optional volume description. (Default=None)')) @cliutils.arg( '--display_description', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--display-description', help=argparse.SUPPRESS) @cliutils.arg( '--volume-type', @@ -2200,6 +2243,9 @@ def do_volume_show(cs, args): help=_('Optional volume type. (Default=None)')) @cliutils.arg( '--volume_type', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--volume-type', help=argparse.SUPPRESS) @cliutils.arg( '--availability-zone', metavar='', @@ -2338,6 +2384,9 @@ def do_volume_snapshot_show(cs, args): help=_('Optional snapshot name. (Default=None)')) @cliutils.arg( '--display_name', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--display-name', help=argparse.SUPPRESS) @cliutils.arg( '--display-description', @@ -2346,6 +2395,9 @@ def do_volume_snapshot_show(cs, args): help=_('Optional snapshot description. (Default=None)')) @cliutils.arg( '--display_description', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--display-description', help=argparse.SUPPRESS) def do_volume_snapshot_create(cs, args): """DEPRECATED: Add a new snapshot.""" @@ -2462,8 +2514,16 @@ def do_get_rdp_console(cs, args): @cliutils.arg('server', metavar='', help=_('Name or ID of server.')) @cliutils.arg( - '--console_type', default='serial', + '--console-type', + default='serial', help=_('Type of serial console, default="serial".')) +@cliutils.arg( + '--console_type', + default='serial', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--console-type', + help=argparse.SUPPRESS) def do_get_serial_console(cs, args): """Get a serial console to a server.""" if args.console_type not in ('serial',): @@ -2741,6 +2801,9 @@ def do_dns_delete_domain(cs, args): 'in the specified availability zone.')) @cliutils.arg( '--availability_zone', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--availability-zone', help=argparse.SUPPRESS) def do_dns_create_private_domain(cs, args): """Create the specified DNS domain.""" @@ -2925,6 +2988,9 @@ def do_secgroup_delete(cs, args): nargs='?', type=int, const=1, + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--all-tenants', help=argparse.SUPPRESS) def do_secgroup_list(cs, args): """List security groups for the current tenant.""" @@ -3054,6 +3120,9 @@ def _keypair_create(cs, args, name, pub_key): help=_('Path to a public ssh key.')) @cliutils.arg( '--pub_key', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--pub-key', help=argparse.SUPPRESS) @cliutils.arg( '--key-type', @@ -3666,7 +3735,10 @@ def _print_aggregate_details(aggregate): help=_('True in case of block_migration. (Default=False:live_migration)')) @cliutils.arg( '--block_migrate', - action='store_true', + real_action='store_true', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--block-migrate', help=argparse.SUPPRESS) @cliutils.arg( '--disk-over-commit', @@ -3676,7 +3748,10 @@ def _print_aggregate_details(aggregate): help=_('Allow overcommit. (Default=False)')) @cliutils.arg( '--disk_over_commit', - action='store_true', + real_action='store_true', + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--disk-over-commit', help=argparse.SUPPRESS) def do_live_migration(cs, args): """Migrate running server to a new machine.""" @@ -4276,6 +4351,9 @@ def do_quota_defaults(cs, args): @cliutils.arg( '--floating_ips', type=int, + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--floating-ips', help=argparse.SUPPRESS) @cliutils.arg( '--fixed-ips', @@ -4292,6 +4370,9 @@ def do_quota_defaults(cs, args): @cliutils.arg( '--metadata_items', type=int, + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--metadata-items', help=argparse.SUPPRESS) @cliutils.arg( '--injected-files', @@ -4302,6 +4383,9 @@ def do_quota_defaults(cs, args): @cliutils.arg( '--injected_files', type=int, + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--injected-files', help=argparse.SUPPRESS) @cliutils.arg( '--injected-file-content-bytes', @@ -4312,6 +4396,9 @@ def do_quota_defaults(cs, args): @cliutils.arg( '--injected_file_content_bytes', type=int, + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--injected-file-content-bytes', help=argparse.SUPPRESS) @cliutils.arg( '--injected-file-path-bytes', @@ -4417,6 +4504,9 @@ def do_quota_class_show(cs, args): @cliutils.arg( '--floating_ips', type=int, + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--floating-ips', help=argparse.SUPPRESS) @cliutils.arg( '--fixed-ips', @@ -4433,6 +4523,9 @@ def do_quota_class_show(cs, args): @cliutils.arg( '--metadata_items', type=int, + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--metadata-items', help=argparse.SUPPRESS) @cliutils.arg( '--injected-files', @@ -4443,6 +4536,9 @@ def do_quota_class_show(cs, args): @cliutils.arg( '--injected_files', type=int, + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--injected-files', help=argparse.SUPPRESS) @cliutils.arg( '--injected-file-content-bytes', @@ -4453,6 +4549,9 @@ def do_quota_class_show(cs, args): @cliutils.arg( '--injected_file_content_bytes', type=int, + action=shell.DeprecatedAction, + use=_('use "%s"; this option will be removed in ' + 'novaclient 3.3.0.') % '--injected-file-content-bytes', help=argparse.SUPPRESS) @cliutils.arg( '--injected-file-path-bytes', @@ -4744,7 +4843,10 @@ def do_secgroup_delete_default_rule(cs, args): @cliutils.arg( '--policy', default=[], - action='append', + real_action='append', + action=shell.DeprecatedAction, + use=_('use positional parameters; this option will be removed in ' + 'novaclient 3.3.0.'), help=argparse.SUPPRESS) def do_server_group_create(cs, args): """Create a new server group with the specified details."""