Floating IP: Neutron support for "ip floating delete" command
This patch implements "ip floating delete" command for both compute and network. Also includes unit tests. Change-Id: Ie61f0faad65ec90f9d9956ae463412be8d963d05 partial-Bug: 1519502 Related-to: blueprint neutron-client Co-Authored-By: Tang Chen <chen.tang@easystack.cn>
This commit is contained in:
parent
c7c672d4b3
commit
6109dfcf63
@ -2,7 +2,7 @@
|
||||
ip floating
|
||||
===========
|
||||
|
||||
Compute v2
|
||||
Compute v2, Network v2
|
||||
|
||||
ip floating add
|
||||
---------------
|
||||
@ -42,17 +42,16 @@ Create new floating IP address
|
||||
ip floating delete
|
||||
------------------
|
||||
|
||||
Delete a floating IP address
|
||||
Delete floating IP
|
||||
|
||||
.. program:: ip floating delete
|
||||
.. code:: bash
|
||||
.. code:: bash
|
||||
|
||||
os ip floating delete
|
||||
<ip-address>
|
||||
os ip floating delete <floating-ip>
|
||||
|
||||
.. describe:: <ip-address>
|
||||
.. describe:: <floating-ip>
|
||||
|
||||
IP address to delete (ID only)
|
||||
Floating IP to delete (IP address or ID)
|
||||
|
||||
ip floating list
|
||||
----------------
|
||||
|
@ -68,29 +68,6 @@ class CreateFloatingIP(command.ShowOne):
|
||||
return zip(*sorted(six.iteritems(info)))
|
||||
|
||||
|
||||
class DeleteFloatingIP(command.Command):
|
||||
"""Delete a floating IP address"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteFloatingIP, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
"ip_address",
|
||||
metavar="<ip-address>",
|
||||
help="IP address to delete (ID only)",
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
compute_client = self.app.client_manager.compute
|
||||
|
||||
floating_ip = utils.find_resource(
|
||||
compute_client.floating_ips,
|
||||
parsed_args.ip_address,
|
||||
)
|
||||
|
||||
compute_client.floating_ips.delete(floating_ip)
|
||||
|
||||
|
||||
class ListFloatingIP(command.Lister):
|
||||
"""List floating IP addresses"""
|
||||
|
||||
|
40
openstackclient/network/v2/floating_ip.py
Normal file
40
openstackclient/network/v2/floating_ip.py
Normal file
@ -0,0 +1,40 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""IP Floating action implementations"""
|
||||
|
||||
from openstackclient.common import utils
|
||||
from openstackclient.network import common
|
||||
|
||||
|
||||
class DeleteFloatingIP(common.NetworkAndComputeCommand):
|
||||
"""Delete floating IP"""
|
||||
|
||||
def update_parser_common(self, parser):
|
||||
parser.add_argument(
|
||||
'floating_ip',
|
||||
metavar="<floating-ip>",
|
||||
help=("Floating IP to delete (IP address or ID)")
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action_network(self, client, parsed_args):
|
||||
obj = client.find_ip(parsed_args.floating_ip)
|
||||
client.delete_ip(obj)
|
||||
|
||||
def take_action_compute(self, client, parsed_args):
|
||||
obj = utils.find_resource(
|
||||
client.floating_ips,
|
||||
parsed_args.floating_ip,
|
||||
)
|
||||
client.floating_ips.delete(obj.id)
|
@ -126,6 +126,9 @@ class FakeComputev2Client(object):
|
||||
self.security_group_rules = mock.Mock()
|
||||
self.security_group_rules.resource_class = fakes.FakeResource(None, {})
|
||||
|
||||
self.floating_ips = mock.Mock()
|
||||
self.floating_ips.resource_class = fakes.FakeResource(None, {})
|
||||
|
||||
self.auth_token = kwargs['token']
|
||||
|
||||
self.management_url = kwargs['endpoint']
|
||||
|
@ -226,7 +226,6 @@ class FakePort(object):
|
||||
:return:
|
||||
A FakeResource object, with id, name, etc.
|
||||
"""
|
||||
|
||||
# Set default attributes.
|
||||
port_attrs = {
|
||||
'admin_state_up': True,
|
||||
@ -553,3 +552,79 @@ class FakeSubnet(object):
|
||||
subnets.append(FakeSubnet.create_one_subnet(attrs, methods))
|
||||
|
||||
return subnets
|
||||
|
||||
|
||||
class FakeFloatingIP(object):
|
||||
"""Fake one or more floating ip."""
|
||||
|
||||
@staticmethod
|
||||
def create_one_floating_ip(attrs={}, methods={}):
|
||||
"""Create a fake floating ip.
|
||||
|
||||
:param Dictionary attrs:
|
||||
A dictionary with all attributes
|
||||
:param Dictionary methods:
|
||||
A dictionary with all methods
|
||||
:return:
|
||||
A FakeResource object, with id, ip
|
||||
"""
|
||||
# Set default attributes.
|
||||
floating_ip_attrs = {
|
||||
'id': 'floating-ip-id-' + uuid.uuid4().hex,
|
||||
'ip': '1.0.9.0',
|
||||
}
|
||||
|
||||
# Overwrite default attributes.
|
||||
floating_ip_attrs.update(attrs)
|
||||
|
||||
# Set default methods.
|
||||
floating_ip_methods = {}
|
||||
|
||||
# Overwrite default methods.
|
||||
floating_ip_methods.update(methods)
|
||||
|
||||
floating_ip = fakes.FakeResource(
|
||||
info=copy.deepcopy(floating_ip_attrs),
|
||||
methods=copy.deepcopy(floating_ip_methods),
|
||||
loaded=True)
|
||||
return floating_ip
|
||||
|
||||
@staticmethod
|
||||
def create_floating_ips(attrs={}, methods={}, count=2):
|
||||
"""Create multiple fake floating ips.
|
||||
|
||||
:param Dictionary attrs:
|
||||
A dictionary with all attributes
|
||||
:param Dictionary methods:
|
||||
A dictionary with all methods
|
||||
:param int count:
|
||||
The number of floating ips to fake
|
||||
:return:
|
||||
A list of FakeResource objects faking the floating ips
|
||||
"""
|
||||
floating_ips = []
|
||||
for i in range(0, count):
|
||||
floating_ips.append(FakeFloatingIP.create_one_floating_ip(
|
||||
attrs,
|
||||
methods
|
||||
))
|
||||
return floating_ips
|
||||
|
||||
@staticmethod
|
||||
def get_floating_ips(floating_ips=None, count=2):
|
||||
"""Get an iterable MagicMock object with a list of faked floating ips.
|
||||
|
||||
If floating_ips list is provided, then initialize the Mock object
|
||||
with the list. Otherwise create one.
|
||||
|
||||
:param List floating ips:
|
||||
A list of FakeResource objects faking floating ips
|
||||
:param int count:
|
||||
The number of floating ips to fake
|
||||
:return:
|
||||
An iterable Mock object with side_effect set to a list of faked
|
||||
floating ips
|
||||
"""
|
||||
if floating_ips is None:
|
||||
floating_ips = FakeFloatingIP.create_floating_ips(count)
|
||||
return mock.MagicMock(side_effect=floating_ips)
|
||||
|
105
openstackclient/tests/network/v2/test_floating_ip.py
Normal file
105
openstackclient/tests/network/v2/test_floating_ip.py
Normal file
@ -0,0 +1,105 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
import mock
|
||||
|
||||
from openstackclient.network.v2 import floating_ip
|
||||
from openstackclient.tests.compute.v2 import fakes as compute_fakes
|
||||
from openstackclient.tests.network.v2 import fakes as network_fakes
|
||||
|
||||
|
||||
# Tests for Neutron network
|
||||
#
|
||||
class TestFloatingIPNetwork(network_fakes.TestNetworkV2):
|
||||
|
||||
def setUp(self):
|
||||
super(TestFloatingIPNetwork, self).setUp()
|
||||
|
||||
# Get a shortcut to the network client
|
||||
self.network = self.app.client_manager.network
|
||||
|
||||
|
||||
class TestDeleteFloatingIPNetwork(TestFloatingIPNetwork):
|
||||
|
||||
# The floating ip to be deleted.
|
||||
floating_ip = network_fakes.FakeFloatingIP.create_one_floating_ip()
|
||||
|
||||
def setUp(self):
|
||||
super(TestDeleteFloatingIPNetwork, self).setUp()
|
||||
|
||||
self.network.delete_ip = mock.Mock(return_value=self.floating_ip)
|
||||
self.network.find_ip = mock.Mock(return_value=self.floating_ip)
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = floating_ip.DeleteFloatingIP(self.app, self.namespace)
|
||||
|
||||
def test_floating_ip_delete(self):
|
||||
arglist = [
|
||||
self.floating_ip.id,
|
||||
]
|
||||
verifylist = [
|
||||
('floating_ip', self.floating_ip.id),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.network.find_ip.assert_called_with(self.floating_ip.id)
|
||||
self.network.delete_ip.assert_called_with(self.floating_ip)
|
||||
self.assertIsNone(result)
|
||||
|
||||
|
||||
# Tests for Nova network
|
||||
#
|
||||
class TestFloatingIPCompute(compute_fakes.TestComputev2):
|
||||
|
||||
def setUp(self):
|
||||
super(TestFloatingIPCompute, self).setUp()
|
||||
|
||||
# Get a shortcut to the compute client
|
||||
self.compute = self.app.client_manager.compute
|
||||
|
||||
|
||||
class TestDeleteFloatingIPCompute(TestFloatingIPCompute):
|
||||
|
||||
# The floating ip to be deleted.
|
||||
floating_ip = network_fakes.FakeFloatingIP.create_one_floating_ip()
|
||||
|
||||
def setUp(self):
|
||||
super(TestDeleteFloatingIPCompute, self).setUp()
|
||||
|
||||
self.app.client_manager.network_endpoint_enabled = False
|
||||
|
||||
self.compute.floating_ips.delete.return_value = None
|
||||
|
||||
# Return value of utils.find_resource()
|
||||
self.compute.floating_ips.get.return_value = self.floating_ip
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = floating_ip.DeleteFloatingIP(self.app, None)
|
||||
|
||||
def test_floating_ip_delete(self):
|
||||
arglist = [
|
||||
self.floating_ip.id,
|
||||
]
|
||||
verifylist = [
|
||||
('floating_ip', self.floating_ip.id),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.compute.floating_ips.delete.assert_called_with(
|
||||
self.floating_ip.id
|
||||
)
|
||||
self.assertIsNone(result)
|
@ -91,10 +91,8 @@ openstack.compute.v2 =
|
||||
|
||||
ip_floating_add = openstackclient.compute.v2.floatingip:AddFloatingIP
|
||||
ip_floating_create = openstackclient.compute.v2.floatingip:CreateFloatingIP
|
||||
ip_floating_delete = openstackclient.compute.v2.floatingip:DeleteFloatingIP
|
||||
ip_floating_list = openstackclient.compute.v2.floatingip:ListFloatingIP
|
||||
ip_floating_remove = openstackclient.compute.v2.floatingip:RemoveFloatingIP
|
||||
|
||||
ip_floating_pool_list = openstackclient.compute.v2.floatingippool:ListFloatingIPPool
|
||||
|
||||
keypair_create = openstackclient.compute.v2.keypair:CreateKeypair
|
||||
@ -327,6 +325,7 @@ openstack.image.v2 =
|
||||
image_set = openstackclient.image.v2.image:SetImage
|
||||
|
||||
openstack.network.v2 =
|
||||
ip_floating_delete = openstackclient.network.v2.floating_ip:DeleteFloatingIP
|
||||
network_create = openstackclient.network.v2.network:CreateNetwork
|
||||
network_delete = openstackclient.network.v2.network:DeleteNetwork
|
||||
network_list = openstackclient.network.v2.network:ListNetwork
|
||||
|
Loading…
x
Reference in New Issue
Block a user