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:
parent
c3b5365cdf
commit
578c39865d
@ -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")
|
||||
|
@ -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())
|
||||
|
||||
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
|
||||
|
@ -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)
|
||||
|
46
novaclient/tests/functional/v2/test_networks.py
Normal file
46
novaclient/tests/functional/v2/test_networks.py
Normal 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')
|
@ -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']
|
||||
|
@ -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()
|
||||
|
@ -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"))
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
# 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).
|
||||
|
@ -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.
|
Loading…
Reference in New Issue
Block a user