Skip to content

Commit 860dbc1

Browse files
author
Tang Chen
committed
[Floating IP] Neutron support for "ip floating create" command
This patch adds --subnet, --port, --floating-ip-address and --fixed-ip-address options only. Project related options will be added in another patch because it relates to identity v2 and v3, which will make the unit tests too complicated in one single patch. Change-Id: I3cce4404a114ff128b74e4596f0e847be2846b17 Partial-Bug: 1519502 Related-to: blueprint neutron-client
1 parent 4b4349e commit 860dbc1

6 files changed

Lines changed: 281 additions & 27 deletions

File tree

doc/source/command-objects/ip-floating.rst

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,35 @@ Create new floating IP address
3333
.. code:: bash
3434
3535
os ip floating create
36-
<pool>
36+
[--subnet <subnet>]
37+
[--port <port>]
38+
[--floating-ip-address <floating-ip-address>]
39+
[--fixed-ip-address <fixed-ip-address>]
40+
<network>
3741
38-
.. describe:: <pool>
42+
.. option:: --subnet <subnet>
3943

40-
Pool to fetch IP address from (name or ID)
44+
Subnet on which you want to create the floating IP (name or ID)
45+
(Network v2 only)
46+
47+
.. option:: --port <port>
48+
49+
Port to be associated with the floating IP (name or ID)
50+
(Network v2 only)
51+
52+
.. option:: --floating-ip-address <floating-ip-address>
53+
54+
Floating IP address
55+
(Network v2 only)
56+
57+
.. option:: --fixed-ip-address <fixed-ip-address>
58+
59+
Fixed IP address mapped to the floating IP
60+
(Network v2 only)
61+
62+
.. describe:: <network>
63+
64+
Network to allocate floating IP from (name or ID)
4165

4266
ip floating delete
4367
------------------

openstackclient/compute/v2/floatingip.py

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515

1616
"""Floating IP action implementations"""
1717

18-
import six
19-
2018
from openstackclient.common import command
2119
from openstackclient.common import utils
2220

@@ -47,27 +45,6 @@ def take_action(self, parsed_args):
4745
server.add_floating_ip(parsed_args.ip_address)
4846

4947

50-
class CreateFloatingIP(command.ShowOne):
51-
"""Create new floating IP address"""
52-
53-
def get_parser(self, prog_name):
54-
parser = super(CreateFloatingIP, self).get_parser(prog_name)
55-
parser.add_argument(
56-
'pool',
57-
metavar='<pool>',
58-
help='Pool to fetch IP address from (name or ID)',
59-
)
60-
return parser
61-
62-
def take_action(self, parsed_args):
63-
compute_client = self.app.client_manager.compute
64-
floating_ip = compute_client.floating_ips.create(parsed_args.pool)
65-
66-
info = {}
67-
info.update(floating_ip._info)
68-
return zip(*sorted(six.iteritems(info)))
69-
70-
7148
class RemoveFloatingIP(command.Command):
7249
"""Remove floating IP address from server"""
7350

openstackclient/network/v2/floating_ip.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,89 @@ def _get_columns(item):
2525
return tuple(sorted(columns))
2626

2727

28+
def _get_attrs(client_manager, parsed_args):
29+
attrs = {}
30+
network_client = client_manager.network
31+
32+
if parsed_args.network is not None:
33+
network = network_client.find_network(parsed_args.network,
34+
ignore_missing=False)
35+
attrs['floating_network_id'] = network.id
36+
37+
if parsed_args.subnet is not None:
38+
subnet = network_client.find_subnet(parsed_args.subnet,
39+
ignore_missing=False)
40+
attrs['subnet_id'] = subnet.id
41+
42+
if parsed_args.port is not None:
43+
port = network_client.find_port(parsed_args.port,
44+
ignore_missing=False)
45+
attrs['port_id'] = port.id
46+
47+
if parsed_args.floating_ip_address is not None:
48+
attrs['floating_ip_address'] = parsed_args.floating_ip_address
49+
50+
if parsed_args.fixed_ip_address is not None:
51+
attrs['fixed_ip_address'] = parsed_args.fixed_ip_address
52+
53+
return attrs
54+
55+
56+
class CreateFloatingIP(common.NetworkAndComputeShowOne):
57+
"""Create floating IP"""
58+
59+
def update_parser_common(self, parser):
60+
# In Compute v2 network, floating IPs could be allocated from floating
61+
# IP pools, which are actually external networks. So deprecate the
62+
# parameter "pool", and use "network" instead.
63+
parser.add_argument(
64+
'network',
65+
metavar='<network>',
66+
help='Network to allocate floating IP from (name or ID)',
67+
)
68+
return parser
69+
70+
def update_parser_network(self, parser):
71+
parser.add_argument(
72+
'--subnet',
73+
metavar='<subnet>',
74+
help="Subnet on which you want to create the floating IP "
75+
"(name or ID)"
76+
)
77+
parser.add_argument(
78+
'--port',
79+
metavar='<port>',
80+
help="Port to be associated with the floating IP "
81+
"(name or ID)"
82+
)
83+
parser.add_argument(
84+
'--floating-ip-address',
85+
metavar='<floating-ip-address>',
86+
dest='floating_ip_address',
87+
help="Floating IP address"
88+
)
89+
parser.add_argument(
90+
'--fixed-ip-address',
91+
metavar='<fixed-ip-address>',
92+
dest='fixed_ip_address',
93+
help="Fixed IP address mapped to the floating IP"
94+
)
95+
return parser
96+
97+
def take_action_network(self, client, parsed_args):
98+
attrs = _get_attrs(self.app.client_manager, parsed_args)
99+
obj = client.create_ip(**attrs)
100+
columns = _get_columns(obj)
101+
data = utils.get_item_properties(obj, columns)
102+
return (columns, data)
103+
104+
def take_action_compute(self, client, parsed_args):
105+
obj = client.floating_ips.create(parsed_args.network)
106+
columns = _get_columns(obj._info)
107+
data = utils.get_dict_properties(obj._info, columns)
108+
return (columns, data)
109+
110+
28111
class DeleteFloatingIP(common.NetworkAndComputeCommand):
29112
"""Delete floating IP"""
30113

openstackclient/tests/network/v2/test_floating_ip.py

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from openstackclient.network.v2 import floating_ip
1717
from openstackclient.tests.compute.v2 import fakes as compute_fakes
1818
from openstackclient.tests.network.v2 import fakes as network_fakes
19+
from openstackclient.tests import utils as tests_utils
1920

2021

2122
# Tests for Neutron network
@@ -29,6 +30,115 @@ def setUp(self):
2930
self.network = self.app.client_manager.network
3031

3132

33+
class TestCreateFloatingIPNetwork(TestFloatingIPNetwork):
34+
35+
# Fake data for option tests.
36+
floating_network = network_fakes.FakeNetwork.create_one_network()
37+
subnet = network_fakes.FakeSubnet.create_one_subnet()
38+
port = network_fakes.FakePort.create_one_port()
39+
40+
# The floating ip to be deleted.
41+
floating_ip = network_fakes.FakeFloatingIP.create_one_floating_ip(
42+
attrs={
43+
'floating_network_id': floating_network.id,
44+
'port_id': port.id,
45+
}
46+
)
47+
48+
columns = (
49+
'dns_domain',
50+
'dns_name',
51+
'fixed_ip_address',
52+
'floating_ip_address',
53+
'floating_network_id',
54+
'id',
55+
'port_id',
56+
'project_id',
57+
'router_id',
58+
'status',
59+
)
60+
61+
data = (
62+
floating_ip.dns_domain,
63+
floating_ip.dns_name,
64+
floating_ip.fixed_ip_address,
65+
floating_ip.floating_ip_address,
66+
floating_ip.floating_network_id,
67+
floating_ip.id,
68+
floating_ip.port_id,
69+
floating_ip.project_id,
70+
floating_ip.router_id,
71+
floating_ip.status,
72+
)
73+
74+
def setUp(self):
75+
super(TestCreateFloatingIPNetwork, self).setUp()
76+
77+
self.network.create_ip = mock.Mock(return_value=self.floating_ip)
78+
79+
self.network.find_network = mock.Mock(
80+
return_value=self.floating_network)
81+
self.network.find_subnet = mock.Mock(return_value=self.subnet)
82+
self.network.find_port = mock.Mock(return_value=self.port)
83+
84+
# Get the command object to test
85+
self.cmd = floating_ip.CreateFloatingIP(self.app, self.namespace)
86+
87+
def test_create_no_options(self):
88+
arglist = []
89+
verifylist = []
90+
91+
# Missing required args should bail here
92+
self.assertRaises(tests_utils.ParserException, self.check_parser,
93+
self.cmd, arglist, verifylist)
94+
95+
def test_create_default_options(self):
96+
arglist = [
97+
self.floating_ip.floating_network_id,
98+
]
99+
verifylist = [
100+
('network', self.floating_ip.floating_network_id),
101+
]
102+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
103+
104+
columns, data = self.cmd.take_action(parsed_args)
105+
106+
self.network.create_ip.assert_called_once_with(**{
107+
'floating_network_id': self.floating_ip.floating_network_id,
108+
})
109+
self.assertEqual(self.columns, columns)
110+
self.assertEqual(self.data, data)
111+
112+
def test_create_all_options(self):
113+
arglist = [
114+
'--subnet', self.subnet.id,
115+
'--port', self.floating_ip.port_id,
116+
'--floating-ip-address', self.floating_ip.floating_ip_address,
117+
'--fixed-ip-address', self.floating_ip.fixed_ip_address,
118+
self.floating_ip.floating_network_id,
119+
]
120+
verifylist = [
121+
('subnet', self.subnet.id),
122+
('port', self.floating_ip.port_id),
123+
('floating_ip_address', self.floating_ip.floating_ip_address),
124+
('fixed_ip_address', self.floating_ip.fixed_ip_address),
125+
('network', self.floating_ip.floating_network_id),
126+
]
127+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
128+
129+
columns, data = self.cmd.take_action(parsed_args)
130+
131+
self.network.create_ip.assert_called_once_with(**{
132+
'subnet_id': self.subnet.id,
133+
'port_id': self.floating_ip.port_id,
134+
'floating_ip_address': self.floating_ip.floating_ip_address,
135+
'fixed_ip_address': self.floating_ip.fixed_ip_address,
136+
'floating_network_id': self.floating_ip.floating_network_id,
137+
})
138+
self.assertEqual(self.columns, columns)
139+
self.assertEqual(self.data, data)
140+
141+
32142
class TestDeleteFloatingIPNetwork(TestFloatingIPNetwork):
33143

34144
# The floating ip to be deleted.
@@ -169,6 +279,62 @@ def setUp(self):
169279
self.compute = self.app.client_manager.compute
170280

171281

282+
class TestCreateFloatingIPCompute(TestFloatingIPCompute):
283+
284+
# The floating ip to be deleted.
285+
floating_ip = compute_fakes.FakeFloatingIP.create_one_floating_ip()
286+
287+
columns = (
288+
'fixed_ip',
289+
'id',
290+
'instance_id',
291+
'ip',
292+
'pool',
293+
)
294+
295+
data = (
296+
floating_ip.fixed_ip,
297+
floating_ip.id,
298+
floating_ip.instance_id,
299+
floating_ip.ip,
300+
floating_ip.pool,
301+
)
302+
303+
def setUp(self):
304+
super(TestCreateFloatingIPCompute, self).setUp()
305+
306+
self.app.client_manager.network_endpoint_enabled = False
307+
308+
self.compute.floating_ips.create.return_value = self.floating_ip
309+
310+
# Get the command object to test
311+
self.cmd = floating_ip.CreateFloatingIP(self.app, None)
312+
313+
def test_create_no_options(self):
314+
arglist = []
315+
verifylist = []
316+
317+
# Missing required args should bail here
318+
self.assertRaises(tests_utils.ParserException, self.check_parser,
319+
self.cmd, arglist, verifylist)
320+
321+
def test_create_default_options(self):
322+
arglist = [
323+
self.floating_ip.pool,
324+
]
325+
verifylist = [
326+
('network', self.floating_ip.pool),
327+
]
328+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
329+
330+
columns, data = self.cmd.take_action(parsed_args)
331+
332+
self.compute.floating_ips.create.assert_called_once_with(
333+
self.floating_ip.pool)
334+
self.assertEqual(self.columns, columns)
335+
self.assertEqual(self.data, data)
336+
337+
172338
class TestDeleteFloatingIPCompute(TestFloatingIPCompute):
173339

174340
# The floating ip to be deleted.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
features:
3+
- Command ``ip floating create`` is now available for neutron network.
4+
[Bug `1519502 <https://bugs.launchpad.net/python-openstackclient/+bug/1519502>`_]

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ openstack.compute.v2 =
9191
ip_fixed_remove = openstackclient.compute.v2.fixedip:RemoveFixedIP
9292

9393
ip_floating_add = openstackclient.compute.v2.floatingip:AddFloatingIP
94-
ip_floating_create = openstackclient.compute.v2.floatingip:CreateFloatingIP
9594
ip_floating_remove = openstackclient.compute.v2.floatingip:RemoveFloatingIP
9695
ip_floating_pool_list = openstackclient.compute.v2.floatingippool:ListFloatingIPPool
9796

@@ -322,6 +321,7 @@ openstack.image.v2 =
322321
image_set = openstackclient.image.v2.image:SetImage
323322

324323
openstack.network.v2 =
324+
ip_floating_create = openstackclient.network.v2.floating_ip:CreateFloatingIP
325325
ip_floating_delete = openstackclient.network.v2.floating_ip:DeleteFloatingIP
326326
ip_floating_list = openstackclient.network.v2.floating_ip:ListFloatingIP
327327
ip_floating_show = openstackclient.network.v2.floating_ip:ShowFloatingIP

0 commit comments

Comments
 (0)