Deprecate network-* commands and clamp to microversion 2.35

This introduces a helper to clamp the client microversion to 2.35,
which is the last version to support the network proxy. We print a
deprecation warning if those commands are used, and mark them as
deprecated in the help text.

This is a network-specific user-friendly bit of sugar to make sure
that nova-network users aren't cut out before we actually drop the
support for it on the server side.

Note that quotas and limits are special because only the network
related resources in those are not returned with 2.36. So this
change handles 2.36 separately for quota-update and
quota-class-update, and deprecates the network resource quota
update arguments for <2.35 as an indication those are going away.

As expected, several of the functional tests have to be updated
to work with the new world that is microversion 2.36.

Related to blueprint deprecate-api-proxies

Co-Authored-By: Matt Riedemann <mriedem@us.ibm.com>

Change-Id: Id68c2dbef29b201aa7c8ef9417432feb5596529a
This commit is contained in:
Matt Riedemann 2016-08-18 10:03:11 -04:00 committed by Dan Smith
parent c3b5365cdf
commit 578c39865d
11 changed files with 461 additions and 9 deletions

View File

@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
# when client supported the max version, and bumped sequentially, otherwise
# the client may break due to server side new version may include some
# backward incompatible change.
API_MAX_VERSION = api_versions.APIVersion("2.35")
API_MAX_VERSION = api_versions.APIVersion("2.36")

View File

@ -214,7 +214,16 @@ class ClientTestBase(testtools.TestCase):
# pick some reasonable flavor / image combo
self.flavor = pick_flavor(self.client.flavors.list())
self.image = pick_image(self.glance.images.list())
self.network = pick_network(self.client.networks.list())
tested_api_version = self.client.api_version
proxy_api_version = novaclient.api_versions.APIVersion('2.35')
if tested_api_version > proxy_api_version:
self.client.api_version = proxy_api_version
try:
# TODO(mriedem): Get the networks from neutron if using neutron.
self.network = pick_network(self.client.networks.list())
finally:
self.client.api_version = tested_api_version
# create a CLI client in case we'd like to do CLI
# testing. tempest.lib does this really weird thing where it

View File

@ -56,13 +56,12 @@ class TestServersBootNovaClient(base.ClientTestBase):
self._boot_server_with_legacy_bdm()
def test_boot_server_with_net_name(self):
network = self.client.networks.list()[0]
server_info = self.nova("boot", params=(
"%(name)s --flavor %(flavor)s --image %(image)s --poll "
"--nic net-name=%(net-name)s" % {"name": str(uuid.uuid4()),
"image": self.image.id,
"flavor": self.flavor.id,
"net-name": network.label}))
"net-name": self.network.label}))
server_id = self._get_value_from_the_table(server_info, "id")
self.client.servers.delete(server_id)

View File

@ -0,0 +1,46 @@
# Copyright 2016 Red Hat, Inc.
# 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.
from novaclient.tests.functional import base
class TestNetworkCommandsV2_36(base.ClientTestBase):
"""Deprecated network command functional tests."""
# Proxy APIs were deprecated in 2.36 but the CLI should fallback to 2.35
# and emit a warning.
COMPUTE_API_VERSION = "2.36"
def test_command_deprecation(self):
output = self.nova('network-list', merge_stderr=True)
self.assertIn(
'is deprecated', output,
'network-list command did not print deprecation warning')
def test_limits(self):
"""Tests that 2.36 won't return network-related resource limits and
the CLI output won't show them.
"""
output = self.nova('limits')
# assert that SecurityGroups isn't in the table output
self.assertRaises(ValueError, self._get_value_from_the_table,
output, 'SecurityGroups')
def test_quota_show(self):
"""Tests that 2.36 won't return network-related resource quotas and
the CLI output won't show them.
"""
output = self.nova('quota-show')
# assert that security_groups isn't in the table output
self.assertRaises(ValueError, self._get_value_from_the_table,
output, 'security_groups')

View File

@ -13,10 +13,10 @@
from novaclient.tests.functional.v2.legacy import test_quotas
class TestQuotasNovaClient(test_quotas.TestQuotasNovaClient):
class TestQuotasNovaClient2_35(test_quotas.TestQuotasNovaClient):
"""Nova quotas functional tests."""
COMPUTE_API_VERSION = "2.latest"
COMPUTE_API_VERSION = "2.35"
_quota_resources = ['instances', 'cores', 'ram',
'floating_ips', 'fixed_ips', 'metadata_items',
@ -47,3 +47,17 @@ class TestQuotasNovaClient(test_quotas.TestQuotasNovaClient):
for quota_name in self._quota_resources:
self.assertEqual(getattr(original_quotas, quota_name),
getattr(updated_quotas, quota_name) - difference)
class TestQuotasNovaClient2_36(TestQuotasNovaClient2_35):
"""Nova quotas functional tests."""
COMPUTE_API_VERSION = "2.latest"
# The 2.36 microversion stops proxying network quota resources like
# floating/fixed IPs and security groups/rules.
_quota_resources = ['instances', 'cores', 'ram',
'metadata_items', 'injected_files',
'injected_file_content_bytes',
'injected_file_path_bytes', 'key_pairs',
'server_groups', 'server_group_members']

View File

@ -10,6 +10,10 @@
# License for the specific language governing permissions and limitations
# under the License.
import six
from tempest.lib import exceptions
from novaclient import api_versions
from novaclient.tests.functional.v2.legacy import test_readonly_nova
@ -22,3 +26,13 @@ class SimpleReadOnlyNovaClientTest(
"""
COMPUTE_API_VERSION = "2.latest"
def test_admin_image_list(self):
# The nova images proxy API returns a 404 after 2.35.
if self.client.api_version > api_versions.APIVersion('2.35'):
ex = self.assertRaises(exceptions.CommandFailed,
super(SimpleReadOnlyNovaClientTest, self).
test_admin_image_list)
self.assertIn('NotFound', six.text_type(ex))
else:
super(SimpleReadOnlyNovaClientTest, self).test_admin_image_list()

View File

@ -22,7 +22,6 @@ class TestVirtualInterfacesNovaClient(
def test_virtual_interface_list(self):
output = super(TestVirtualInterfacesNovaClient,
self).test_virtual_interface_list()
network = self.client.networks.list()[0]
self.assertEqual(network.id,
self.assertEqual(self.network.id,
self._get_column_value_from_single_row_table(
output, "Network ID"))

View File

@ -693,6 +693,38 @@ class ShellTest(utils.TestCase):
},
)
@mock.patch('novaclient.v2.client.Client.has_neutron', return_value=False)
def test_boot_nics_net_name_nova_net_2_36(self, has_neutron):
orig_find_network = novaclient.v2.shell._find_network_id_novanet
def stubbed_find_network(cs, net_name):
# assert that we dropped back to 2.35
self.assertEqual(api_versions.APIVersion('2.35'),
cs.client.api_version)
return orig_find_network(cs, net_name)
cmd = ('boot --image %s --flavor 1 '
'--nic net-name=1 some-server' % FAKE_UUID_1)
with mock.patch.object(novaclient.v2.shell, '_find_network_id_novanet',
side_effect=stubbed_find_network) as find_net:
self.run_command(cmd, api_version='2.36')
find_net.assert_called_once_with(self.shell.cs, '1')
self.assert_called_anytime(
'POST', '/servers',
{
'server': {
'flavorRef': '1',
'name': 'some-server',
'imageRef': FAKE_UUID_1,
'min_count': 1,
'max_count': 1,
'networks': [
{'uuid': '1'},
],
},
},
)
@mock.patch('novaclient.v2.client.Client.has_neutron', return_value=True)
def test_boot_nics_net_name_neutron(self, has_neutron):
cmd = ('boot --image %s --flavor 1 '
@ -3271,3 +3303,39 @@ class PollForStatusTestCase(utils.TestCase):
action=action,
show_progress=True,
silent=False)
class ShellUtilTest(utils.TestCase):
def test_deprecated_network_newer(self):
@novaclient.v2.shell.deprecated_network
def tester(cs):
'foo'
self.assertEqual(api_versions.APIVersion('2.35'),
cs.api_version)
cs = mock.MagicMock()
cs.api_version = api_versions.APIVersion('2.9999')
tester(cs)
self.assertEqual('DEPRECATED: foo', tester.__doc__)
def test_deprecated_network_older(self):
@novaclient.v2.shell.deprecated_network
def tester(cs):
'foo'
# since we didn't need to adjust the api_version the mock won't
# have cs.client.api_version set on it
self.assertFalse(hasattr(cs, 'client'))
# we have to set the attribute back on cs so the decorator can
# set the value on it when we return from this wrapped function
setattr(cs, 'client', mock.MagicMock())
cs = mock.MagicMock()
cs.api_version = api_versions.APIVersion('2.1')
# we have to delete the cs.client attribute so hasattr won't return a
# false positive in the wrapped function
del cs.client
tester(cs)
self.assertEqual('DEPRECATED: foo', tester.__doc__)
# the deprecated_network decorator will set cs.client.api_version
# after calling the wrapped function
self.assertEqual(cs.api_version, cs.api_version)

View File

@ -15,6 +15,7 @@
from novaclient import base
from novaclient.i18n import _
from novaclient import utils
from novaclient.v2 import shell
class TenantNetwork(base.Resource):
@ -60,6 +61,7 @@ def do_net(cs, args):
@utils.arg('network_id', metavar='<network_id>', help='ID of network')
@shell.deprecated_network
def do_tenant_network_show(cs, args):
"""
Show a tenant network.
@ -75,6 +77,7 @@ def do_net_list(cs, args):
do_tenant_network_list(cs, args)
@shell.deprecated_network
def do_tenant_network_list(cs, args):
"""
List tenant networks.
@ -106,6 +109,7 @@ def do_net_create(cs, args):
'cidr',
metavar='<cidr>',
help=_('IP block to allocate from (ex. 172.16.0.0/24 or 2001:DB8::/64)'))
@shell.deprecated_network
def do_tenant_network_create(cs, args):
"""
Create a tenant network.
@ -123,6 +127,7 @@ def do_net_delete(cs, args):
@utils.arg('network_id', metavar='<network_id>', help='ID of network')
@shell.deprecated_network
def do_tenant_network_delete(cs, args):
"""
Delete a tenant network.

View File

@ -21,6 +21,7 @@ from __future__ import print_function
import argparse
import copy
import datetime
import functools
import getpass
import locale
import logging
@ -76,6 +77,28 @@ def emit_image_deprecation_warning(command_name):
'instead.' % command_name, file=sys.stderr)
def deprecated_network(fn):
@functools.wraps(fn)
def wrapped(cs, *args, **kwargs):
command_name = '-'.join(fn.__name__.split('_')[1:])
print('WARNING: Command %s is deprecated and will be removed '
'after Nova 15.0.0 is released. Use python-neutronclient '
'or python-openstackclient instead.' % command_name,
file=sys.stderr)
# The network proxy API methods were deprecated in 2.36 and will return
# a 404 so we fallback to 2.35 to maintain a transition for CLI users.
want_version = api_versions.APIVersion('2.35')
cur_version = cs.api_version
if cs.api_version > want_version:
cs.api_version = want_version
try:
return fn(cs, *args, **kwargs)
finally:
cs.api_version = cur_version
wrapped.__doc__ = 'DEPRECATED: ' + fn.__doc__
return wrapped
def _key_value_pairing(text):
try:
(k, v) = text.split('=', 1)
@ -954,6 +977,7 @@ def do_flavor_access_remove(cs, args):
@utils.arg(
'project_id', metavar='<project_id>',
help=_('The ID of the project.'))
@deprecated_network
def do_scrub(cs, args):
"""Delete networks and security groups associated with a project."""
networks_list = cs.networks.list()
@ -975,6 +999,7 @@ def do_scrub(cs, args):
metavar='<fields>',
help=_('Comma-separated list of fields to display. '
'Use the show command to see which fields are available.'))
@deprecated_network
def do_network_list(cs, args):
"""Print a list of available networks."""
network_list = cs.networks.list()
@ -989,6 +1014,7 @@ def do_network_list(cs, args):
'network',
metavar='<network>',
help=_("UUID or label of network."))
@deprecated_network
def do_network_show(cs, args):
"""Show details about the given network."""
network = utils.find_resource(cs.networks, args.network)
@ -999,6 +1025,7 @@ def do_network_show(cs, args):
'network',
metavar='<network>',
help=_("UUID or label of network."))
@deprecated_network
def do_network_delete(cs, args):
"""Delete network by label or id."""
network = utils.find_resource(cs.networks, args.network)
@ -1025,6 +1052,7 @@ def do_network_delete(cs, args):
'network',
metavar='<network>',
help=_("UUID of network."))
@deprecated_network
def do_network_disassociate(cs, args):
"""Disassociate host and/or project from the given network."""
if args.host_only:
@ -1043,6 +1071,7 @@ def do_network_disassociate(cs, args):
'host',
metavar='<host>',
help=_("Name of host"))
@deprecated_network
def do_network_associate_host(cs, args):
"""Associate host with network."""
cs.networks.associate_host(args.network, args.host)
@ -1052,6 +1081,7 @@ def do_network_associate_host(cs, args):
'network',
metavar='<network>',
help=_("UUID of network."))
@deprecated_network
def do_network_associate_project(cs, args):
"""Associate project with network."""
cs.networks.associate_project(args.network)
@ -1182,6 +1212,7 @@ def _filter_network_create_options(args):
'--allowed-end',
dest="allowed_end",
help=_('End of allowed addresses for instances.'))
@deprecated_network
def do_network_create(cs, args):
"""Create a network."""
@ -2291,7 +2322,16 @@ def _find_network_id(cs, net_name):
if cs.has_neutron():
return _find_network_id_neutron(cs, net_name)
else:
return _find_network_id_novanet(cs, net_name)
# The network proxy API methods were deprecated in 2.36 and will return
# a 404 so we fallback to 2.35 to maintain a transition for CLI users.
want_version = api_versions.APIVersion('2.35')
cur_version = cs.api_version
if cs.api_version > want_version:
cs.api_version = want_version
try:
return _find_network_id_novanet(cs, net_name)
finally:
cs.api_version = cur_version
def _find_network_id_novanet(cs, net_name):
@ -2663,12 +2703,14 @@ def do_list_secgroup(cs, args):
help=_('Name of Floating IP Pool. (Optional)'),
nargs='?',
default=None)
@deprecated_network
def do_floating_ip_create(cs, args):
"""Allocate a floating IP for the current tenant."""
_print_floating_ip_list([cs.floating_ips.create(pool=args.pool)])
@utils.arg('address', metavar='<address>', help=_('IP of Floating IP.'))
@deprecated_network
def do_floating_ip_delete(cs, args):
"""De-allocate a floating IP."""
floating_ips = cs.floating_ips.list()
@ -2679,11 +2721,13 @@ def do_floating_ip_delete(cs, args):
args.address)
@deprecated_network
def do_floating_ip_list(cs, _args):
"""List floating IPs."""
_print_floating_ip_list(cs.floating_ips.list())
@deprecated_network
def do_floating_ip_pool_list(cs, _args):
"""List all floating IP pools."""
utils.print_list(cs.floating_ip_pools.list(), ['name'])
@ -2692,6 +2736,7 @@ def do_floating_ip_pool_list(cs, _args):
@utils.arg(
'--host', dest='host', metavar='<host>', default=None,
help=_('Filter by host.'))
@deprecated_network
def do_floating_ip_bulk_list(cs, args):
"""List all floating IPs (nova-network only)."""
utils.print_list(cs.floating_ips_bulk.list(args.host), ['project_id',
@ -2709,6 +2754,7 @@ def do_floating_ip_bulk_list(cs, args):
@utils.arg(
'--interface', metavar='<interface>', default=None,
help=_('Interface for new Floating IPs.'))
@deprecated_network
def do_floating_ip_bulk_create(cs, args):
"""Bulk create floating IPs by range (nova-network only)."""
cs.floating_ips_bulk.create(args.ip_range, args.pool, args.interface)
@ -2716,6 +2762,7 @@ def do_floating_ip_bulk_create(cs, args):
@utils.arg('ip_range', metavar='<range>',
help=_('Address range to delete.'))
@deprecated_network
def do_floating_ip_bulk_delete(cs, args):
"""Bulk delete floating IPs by range (nova-network only)."""
cs.floating_ips_bulk.delete(args.ip_range)
@ -2730,6 +2777,7 @@ def _print_domain_list(domain_entries):
'project', 'availability_zone'])
@deprecated_network
def do_dns_domains(cs, args):
"""Print a list of available dns domains."""
domains = cs.dns_domains.domains()
@ -2739,6 +2787,7 @@ def do_dns_domains(cs, args):
@utils.arg('domain', metavar='<domain>', help=_('DNS domain.'))
@utils.arg('--ip', metavar='<ip>', help=_('IP address.'), default=None)
@utils.arg('--name', metavar='<name>', help=_('DNS name.'), default=None)
@deprecated_network
def do_dns_list(cs, args):
"""List current DNS entries for domain and IP or domain and name."""
if not (args.ip or args.name):
@ -2761,6 +2810,7 @@ def do_dns_list(cs, args):
metavar='<type>',
help=_('DNS type (e.g. "A")'),
default='A')
@deprecated_network
def do_dns_create(cs, args):
"""Create a DNS entry for domain, name, and IP."""
cs.dns_entries.create(args.domain, args.name, args.ip, args.type)
@ -2768,12 +2818,14 @@ def do_dns_create(cs, args):
@utils.arg('domain', metavar='<domain>', help=_('DNS domain.'))
@utils.arg('name', metavar='<name>', help=_('DNS name.'))
@deprecated_network
def do_dns_delete(cs, args):
"""Delete the specified DNS entry."""
cs.dns_entries.delete(args.domain, args.name)
@utils.arg('domain', metavar='<domain>', help=_('DNS domain.'))
@deprecated_network
def do_dns_delete_domain(cs, args):
"""Delete the specified DNS domain."""
cs.dns_domains.delete(args.domain)
@ -2786,6 +2838,7 @@ def do_dns_delete_domain(cs, args):
default=None,
help=_('Limit access to this domain to servers '
'in the specified availability zone.'))
@deprecated_network
def do_dns_create_private_domain(cs, args):
"""Create the specified DNS domain."""
cs.dns_domains.create_private(args.domain,
@ -2798,6 +2851,7 @@ def do_dns_create_private_domain(cs, args):
help=_('Limit access to this domain to users '
'of the specified project.'),
default=None)
@deprecated_network
def do_dns_create_public_domain(cs, args):
"""Create the specified DNS domain."""
cs.dns_domains.create_public(args.domain,
@ -2875,6 +2929,7 @@ def _get_secgroup(cs, secgroup):
metavar='<to-port>',
help=_('Port at end of range.'))
@utils.arg('cidr', metavar='<cidr>', help=_('CIDR for address range.'))
@deprecated_network
def do_secgroup_add_rule(cs, args):
"""Add a rule to a security group."""
secgroup = _get_secgroup(cs, args.secgroup)
@ -2903,6 +2958,7 @@ def do_secgroup_add_rule(cs, args):
metavar='<to-port>',
help=_('Port at end of range.'))
@utils.arg('cidr', metavar='<cidr>', help=_('CIDR for address range.'))
@deprecated_network
def do_secgroup_delete_rule(cs, args):
"""Delete a rule from a security group."""
secgroup = _get_secgroup(cs, args.secgroup)
@ -2922,6 +2978,7 @@ def do_secgroup_delete_rule(cs, args):
@utils.arg(
'description', metavar='<description>',
help=_('Description of security group.'))
@deprecated_network
def do_secgroup_create(cs, args):
"""Create a security group."""
secgroup = cs.security_groups.create(args.name, args.description)
@ -2936,6 +2993,7 @@ def do_secgroup_create(cs, args):
@utils.arg(
'description', metavar='<description>',
help=_('Description of security group.'))
@deprecated_network
def do_secgroup_update(cs, args):
"""Update a security group."""
sg = _get_secgroup(cs, args.secgroup)
@ -2947,6 +3005,7 @@ def do_secgroup_update(cs, args):
'secgroup',
metavar='<secgroup>',
help=_('ID or name of security group.'))
@deprecated_network
def do_secgroup_delete(cs, args):
"""Delete a security group."""
secgroup = _get_secgroup(cs, args.secgroup)
@ -2964,6 +3023,7 @@ def do_secgroup_delete(cs, args):
default=int(strutils.bool_from_string(
os.environ.get("ALL_TENANTS", 'false'), True)),
help=_('Display information from all tenants (Admin only).'))
@deprecated_network
def do_secgroup_list(cs, args):
"""List security groups for the current tenant."""
search_opts = {'all_tenants': args.all_tenants}
@ -2978,6 +3038,7 @@ def do_secgroup_list(cs, args):
'secgroup',
metavar='<secgroup>',
help=_('ID or name of security group.'))
@deprecated_network
def do_secgroup_list_rules(cs, args):
"""List rules for a security group."""
secgroup = _get_secgroup(cs, args.secgroup)
@ -3004,6 +3065,7 @@ def do_secgroup_list_rules(cs, args):
'to_port',
metavar='<to-port>',
help=_('Port at end of range.'))
@deprecated_network
def do_secgroup_add_group_rule(cs, args):
"""Add a source group rule to a security group."""
secgroup = _get_secgroup(cs, args.secgroup)
@ -3042,6 +3104,7 @@ def do_secgroup_add_group_rule(cs, args):
'to_port',
metavar='<to-port>',
help=_('Port at end of range.'))
@deprecated_network
def do_secgroup_delete_group_rule(cs, args):
"""Delete a source group rule from a security group."""
secgroup = _get_secgroup(cs, args.secgroup)
@ -3973,6 +4036,7 @@ def _print_fixed_ip(cs, fixed_ip):
@utils.arg('fixed_ip', metavar='<fixed_ip>', help=_('Fixed IP Address.'))
@deprecated_network
def do_fixed_ip_get(cs, args):
"""Retrieve info on a fixed IP."""
result = cs.fixed_ips.get(args.fixed_ip)
@ -3980,12 +4044,14 @@ def do_fixed_ip_get(cs, args):
@utils.arg('fixed_ip', metavar='<fixed_ip>', help=_('Fixed IP Address.'))
@deprecated_network
def do_fixed_ip_reserve(cs, args):
"""Reserve a fixed IP."""
cs.fixed_ips.reserve(args.fixed_ip)
@utils.arg('fixed_ip', metavar='<fixed_ip>', help=_('Fixed IP Address.'))
@deprecated_network
def do_fixed_ip_unreserve(cs, args):
"""Unreserve a fixed IP."""
cs.fixed_ips.unreserve(args.fixed_ip)
@ -4450,6 +4516,7 @@ def do_quota_defaults(cs, args):
_quota_show(cs.quotas.defaults(project_id))
@api_versions.wraps("2.0", "2.35")
@utils.arg(
'tenant',
metavar='<tenant-id>',
@ -4479,12 +4546,14 @@ def do_quota_defaults(cs, args):
metavar='<floating-ips>',
type=int,
default=None,
action=shell.DeprecatedAction,
help=_('New value for the "floating-ips" quota.'))
@utils.arg(
'--fixed-ips',
metavar='<fixed-ips>',
type=int,
default=None,
action=shell.DeprecatedAction,
help=_('New value for the "fixed-ips" quota.'))
@utils.arg(
'--metadata-items',
@ -4521,12 +4590,14 @@ def do_quota_defaults(cs, args):
metavar='<security-groups>',
type=int,
default=None,
action=shell.DeprecatedAction,
help=_('New value for the "security-groups" quota.'))
@utils.arg(
'--security-group-rules',
metavar='<security-group-rules>',
type=int,
default=None,
action=shell.DeprecatedAction,
help=_('New value for the "security-group-rules" quota.'))
@utils.arg(
'--server-groups',
@ -4553,6 +4624,88 @@ def do_quota_update(cs, args):
_quota_update(cs.quotas, args.tenant, args)
# 2.36 does not support updating quota for floating IPs, fixed IPs, security
# groups or security group rules.
@api_versions.wraps("2.36")
@utils.arg(
'tenant',
metavar='<tenant-id>',
help=_('ID of tenant to set the quotas for.'))
@utils.arg(
'--user',
metavar='<user-id>',
default=None,
help=_('ID of user to set the quotas for.'))
@utils.arg(
'--instances',
metavar='<instances>',
type=int, default=None,
help=_('New value for the "instances" quota.'))
@utils.arg(
'--cores',
metavar='<cores>',
type=int, default=None,
help=_('New value for the "cores" quota.'))
@utils.arg(
'--ram',
metavar='<ram>',
type=int, default=None,
help=_('New value for the "ram" quota.'))
@utils.arg(
'--metadata-items',
metavar='<metadata-items>',
type=int,
default=None,
help=_('New value for the "metadata-items" quota.'))
@utils.arg(
'--injected-files',
metavar='<injected-files>',
type=int,
default=None,
help=_('New value for the "injected-files" quota.'))
@utils.arg(
'--injected-file-content-bytes',
metavar='<injected-file-content-bytes>',
type=int,
default=None,
help=_('New value for the "injected-file-content-bytes" quota.'))
@utils.arg(
'--injected-file-path-bytes',
metavar='<injected-file-path-bytes>',
type=int,
default=None,
help=_('New value for the "injected-file-path-bytes" quota.'))
@utils.arg(
'--key-pairs',
metavar='<key-pairs>',
type=int,
default=None,
help=_('New value for the "key-pairs" quota.'))
@utils.arg(
'--server-groups',
metavar='<server-groups>',
type=int,
default=None,
help=_('New value for the "server-groups" quota.'))
@utils.arg(
'--server-group-members',
metavar='<server-group-members>',
type=int,
default=None,
help=_('New value for the "server-group-members" quota.'))
@utils.arg(
'--force',
dest='force',
action="store_true",
default=None,
help=_('Whether force update the quota even if the already used and '
'reserved exceeds the new quota.'))
def do_quota_update(cs, args):
"""Update the quotas for a tenant/user."""
_quota_update(cs.quotas, args.tenant, args)
@utils.arg(
'--tenant',
metavar='<tenant-id>',
@ -4580,6 +4733,7 @@ def do_quota_class_show(cs, args):
_quota_show(cs.quota_classes.get(args.class_name))
@api_versions.wraps("2.0", "2.35")
@utils.arg(
'class_name',
metavar='<class>',
@ -4604,12 +4758,14 @@ def do_quota_class_show(cs, args):
metavar='<floating-ips>',
type=int,
default=None,
action=shell.DeprecatedAction,
help=_('New value for the "floating-ips" quota.'))
@utils.arg(
'--fixed-ips',
metavar='<fixed-ips>',
type=int,
default=None,
action=shell.DeprecatedAction,
help=_('New value for the "fixed-ips" quota.'))
@utils.arg(
'--metadata-items',
@ -4646,12 +4802,14 @@ def do_quota_class_show(cs, args):
metavar='<security-groups>',
type=int,
default=None,
action=shell.DeprecatedAction,
help=_('New value for the "security-groups" quota.'))
@utils.arg(
'--security-group-rules',
metavar='<security-group-rules>',
type=int,
default=None,
action=shell.DeprecatedAction,
help=_('New value for the "security-group-rules" quota.'))
@utils.arg(
'--server-groups',
@ -4671,6 +4829,76 @@ def do_quota_class_update(cs, args):
_quota_update(cs.quota_classes, args.class_name, args)
# 2.36 does not support updating quota for floating IPs, fixed IPs, security
# groups or security group rules.
@api_versions.wraps("2.36")
@utils.arg(
'class_name',
metavar='<class>',
help=_('Name of quota class to set the quotas for.'))
@utils.arg(
'--instances',
metavar='<instances>',
type=int, default=None,
help=_('New value for the "instances" quota.'))
@utils.arg(
'--cores',
metavar='<cores>',
type=int, default=None,
help=_('New value for the "cores" quota.'))
@utils.arg(
'--ram',
metavar='<ram>',
type=int, default=None,
help=_('New value for the "ram" quota.'))
@utils.arg(
'--metadata-items',
metavar='<metadata-items>',
type=int,
default=None,
help=_('New value for the "metadata-items" quota.'))
@utils.arg(
'--injected-files',
metavar='<injected-files>',
type=int,
default=None,
help=_('New value for the "injected-files" quota.'))
@utils.arg(
'--injected-file-content-bytes',
metavar='<injected-file-content-bytes>',
type=int,
default=None,
help=_('New value for the "injected-file-content-bytes" quota.'))
@utils.arg(
'--injected-file-path-bytes',
metavar='<injected-file-path-bytes>',
type=int,
default=None,
help=_('New value for the "injected-file-path-bytes" quota.'))
@utils.arg(
'--key-pairs',
metavar='<key-pairs>',
type=int,
default=None,
help=_('New value for the "key-pairs" quota.'))
@utils.arg(
'--server-groups',
metavar='<server-groups>',
type=int,
default=None,
help=_('New value for the "server-groups" quota.'))
@utils.arg(
'--server-group-members',
metavar='<server-group-members>',
type=int,
default=None,
help=_('New value for the "server-group-members" quota.'))
def do_quota_class_update(cs, args):
"""Update the quotas for a quota class."""
_quota_update(cs.quota_classes, args.class_name, args)
@utils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
@utils.arg(
'host', metavar='<host>', nargs='?',
@ -4871,6 +5099,7 @@ def do_server_group_list(cs, args):
_print_server_group_details(cs, server_groups)
@deprecated_network
def do_secgroup_list_default_rules(cs, args):
"""List rules that will be added to the 'default' security group for
new tenants.
@ -4892,6 +5121,7 @@ def do_secgroup_list_default_rules(cs, args):
metavar='<to-port>',
help=_('Port at end of range.'))
@utils.arg('cidr', metavar='<cidr>', help=_('CIDR for address range.'))
@deprecated_network
def do_secgroup_add_default_rule(cs, args):
"""Add a rule to the set of rules that will be added to the 'default'
security group for new tenants (nova-network only).
@ -4916,6 +5146,7 @@ def do_secgroup_add_default_rule(cs, args):
metavar='<to-port>',
help=_('Port at end of range.'))
@utils.arg('cidr', metavar='<cidr>', help=_('CIDR for address range.'))
@deprecated_network
def do_secgroup_delete_default_rule(cs, args):
"""Delete a rule from the set of rules that will be added to the
'default' security group for new tenants (nova-network only).

View File

@ -0,0 +1,67 @@
---
upgrade:
- |
The ability to update the following network-related resources via the
``nova quota-update`` and ``nova quota-class-update`` commands is now
deprecated:
* Fixed IPs
* Floating IPs
* Security Groups
* Security Group Rules
By default the quota and limits CLIs will not update or show those
resources using microversion >= 2.36. You can still use them, however, by
specifying ``--os-compute-api-version 2.35``. Quota information for network
resources should be retrieved from python-neutronclient or
python-openstackclient.
deprecations:
- |
The following commands are now deprecated:
* dns-create
* dns-create-private-domain
* dns-create-public-domain
* dns-delete
* dns-delete-domain
* dns-domains
* dns-list
* fixed-ip-get
* fixed-ip-reserve
* fixed-ip-unreserve
* floating-ip-create
* floating-ip-delete
* floating-ip-list
* floating-ip-pool-list
* floating-ip-bulk-create
* floating-ip-bulk-delete
* floating-ip-bulk-list
* network-create
* network-delete
* network-disassociate
* network-associate-host
* network-associate-project
* network-list
* network-show
* scrub
* secgroup-create
* secgroup-delete
* secgroup-list
* secgroup-update
* secgroup-add-group-rule
* secgroup-delete-group-rule
* secgroup-add-rule
* secgroup-delete-rule
* secgroup-list-rules
* secgroup-list-default-rules
* secgroup-add-default-rule
* secgroup-delete-default-rule
* tenant-network-create
* tenant-network-delete
* tenant-network-list
* tenant-network-show
With the 2.36 microversion these will fail in the API. The CLI will
fallback to passing the 2.35 microversion to ease the transition. Network
resource information should be retrieved from python-neutronclient or
python-openstackclient.