Skip to content

Commit f57e10b

Browse files
author
Hang Yang
committed
Support Neutron Address Group CRUD
Add support for Neutron address group CRUD operations. Subsequent patches will be added to use address groups in security group rules. Change-Id: I3c313fc9329837dde67815901528a34dca98ebcc Implements: blueprint address-groups-in-sg-rules Depends-On: https://review.opendev.org/738274 Depends-On: https://review.opendev.org/745594
1 parent fe98069 commit f57e10b

7 files changed

Lines changed: 1075 additions & 0 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
=============
2+
address group
3+
=============
4+
5+
An **address group** is a group of IPv4 or IPv6 address blocks which could be
6+
referenced as a remote source or destination when creating a security group
7+
rule.
8+
9+
Network v2
10+
11+
.. autoprogram-cliff:: openstack.network.v2
12+
:command: address group *
Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
#
13+
14+
"""Address group action implementations"""
15+
16+
import logging
17+
18+
import netaddr
19+
from osc_lib.command import command
20+
from osc_lib import exceptions
21+
from osc_lib import utils
22+
23+
from openstackclient.i18n import _
24+
from openstackclient.identity import common as identity_common
25+
from openstackclient.network import sdk_utils
26+
27+
28+
LOG = logging.getLogger(__name__)
29+
30+
31+
def _get_columns(item):
32+
column_map = {
33+
'tenant_id': 'project_id',
34+
}
35+
return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
36+
37+
38+
def _format_addresses(addresses):
39+
ret = []
40+
for addr in addresses:
41+
ret.append(str(netaddr.IPNetwork(addr)))
42+
return ret
43+
44+
45+
def _get_attrs(client_manager, parsed_args):
46+
attrs = {}
47+
attrs['name'] = parsed_args.name
48+
if parsed_args.description:
49+
attrs['description'] = parsed_args.description
50+
attrs['addresses'] = _format_addresses(parsed_args.address)
51+
if 'project' in parsed_args and parsed_args.project is not None:
52+
identity_client = client_manager.identity
53+
project_id = identity_common.find_project(
54+
identity_client,
55+
parsed_args.project,
56+
parsed_args.project_domain,
57+
).id
58+
attrs['tenant_id'] = project_id
59+
60+
return attrs
61+
62+
63+
class CreateAddressGroup(command.ShowOne):
64+
_description = _("Create a new Address Group")
65+
66+
def get_parser(self, prog_name):
67+
parser = super(CreateAddressGroup, self).get_parser(prog_name)
68+
parser.add_argument(
69+
'name',
70+
metavar="<name>",
71+
help=_("New address group name")
72+
)
73+
parser.add_argument(
74+
'--description',
75+
metavar="<description>",
76+
help=_("New address group description")
77+
)
78+
parser.add_argument(
79+
"--address",
80+
metavar="<ip-address>",
81+
action='append',
82+
default=[],
83+
help=_("IP address or CIDR "
84+
"(repeat option to set multiple addresses)"),
85+
)
86+
parser.add_argument(
87+
'--project',
88+
metavar="<project>",
89+
help=_("Owner's project (name or ID)")
90+
)
91+
identity_common.add_project_domain_option_to_parser(parser)
92+
93+
return parser
94+
95+
def take_action(self, parsed_args):
96+
client = self.app.client_manager.network
97+
attrs = _get_attrs(self.app.client_manager, parsed_args)
98+
99+
obj = client.create_address_group(**attrs)
100+
display_columns, columns = _get_columns(obj)
101+
data = utils.get_item_properties(obj, columns, formatters={})
102+
103+
return (display_columns, data)
104+
105+
106+
class DeleteAddressGroup(command.Command):
107+
_description = _("Delete address group(s)")
108+
109+
def get_parser(self, prog_name):
110+
parser = super(DeleteAddressGroup, self).get_parser(prog_name)
111+
parser.add_argument(
112+
'address_group',
113+
metavar="<address-group>",
114+
nargs='+',
115+
help=_("Address group(s) to delete (name or ID)")
116+
)
117+
118+
return parser
119+
120+
def take_action(self, parsed_args):
121+
client = self.app.client_manager.network
122+
result = 0
123+
124+
for group in parsed_args.address_group:
125+
try:
126+
obj = client.find_address_group(group, ignore_missing=False)
127+
client.delete_address_group(obj)
128+
except Exception as e:
129+
result += 1
130+
LOG.error(_("Failed to delete address group with "
131+
"name or ID '%(group)s': %(e)s"),
132+
{'group': group, 'e': e})
133+
134+
if result > 0:
135+
total = len(parsed_args.address_group)
136+
msg = (_("%(result)s of %(total)s address groups failed "
137+
"to delete.") % {'result': result, 'total': total})
138+
raise exceptions.CommandError(msg)
139+
140+
141+
class ListAddressGroup(command.Lister):
142+
_description = _("List address groups")
143+
144+
def get_parser(self, prog_name):
145+
parser = super(ListAddressGroup, self).get_parser(prog_name)
146+
147+
parser.add_argument(
148+
'--name',
149+
metavar='<name>',
150+
help=_("List only address groups of given name in output")
151+
)
152+
parser.add_argument(
153+
'--project',
154+
metavar="<project>",
155+
help=_("List address groups according to their project "
156+
"(name or ID)")
157+
)
158+
identity_common.add_project_domain_option_to_parser(parser)
159+
160+
return parser
161+
162+
def take_action(self, parsed_args):
163+
client = self.app.client_manager.network
164+
columns = (
165+
'id',
166+
'name',
167+
'description',
168+
'project_id',
169+
'addresses',
170+
)
171+
column_headers = (
172+
'ID',
173+
'Name',
174+
'Description',
175+
'Project',
176+
'Addresses',
177+
)
178+
attrs = {}
179+
if parsed_args.name:
180+
attrs['name'] = parsed_args.name
181+
if 'project' in parsed_args and parsed_args.project is not None:
182+
identity_client = self.app.client_manager.identity
183+
project_id = identity_common.find_project(
184+
identity_client,
185+
parsed_args.project,
186+
parsed_args.project_domain,
187+
).id
188+
attrs['tenant_id'] = project_id
189+
attrs['project_id'] = project_id
190+
data = client.address_groups(**attrs)
191+
192+
return (column_headers,
193+
(utils.get_item_properties(
194+
s, columns, formatters={},
195+
) for s in data))
196+
197+
198+
class SetAddressGroup(command.Command):
199+
_description = _("Set address group properties")
200+
201+
def get_parser(self, prog_name):
202+
parser = super(SetAddressGroup, self).get_parser(prog_name)
203+
parser.add_argument(
204+
'address_group',
205+
metavar="<address-group>",
206+
help=_("Address group to modify (name or ID)")
207+
)
208+
parser.add_argument(
209+
'--name',
210+
metavar="<name>",
211+
help=_('Set address group name')
212+
)
213+
parser.add_argument(
214+
'--description',
215+
metavar="<description>",
216+
help=_('Set address group description')
217+
)
218+
parser.add_argument(
219+
"--address",
220+
metavar="<ip-address>",
221+
action='append',
222+
default=[],
223+
help=_("IP address or CIDR "
224+
"(repeat option to set multiple addresses)"),
225+
)
226+
return parser
227+
228+
def take_action(self, parsed_args):
229+
client = self.app.client_manager.network
230+
obj = client.find_address_group(
231+
parsed_args.address_group,
232+
ignore_missing=False)
233+
attrs = {}
234+
if parsed_args.name is not None:
235+
attrs['name'] = parsed_args.name
236+
if parsed_args.description is not None:
237+
attrs['description'] = parsed_args.description
238+
if attrs:
239+
client.update_address_group(obj, **attrs)
240+
if parsed_args.address:
241+
client.add_addresses_to_address_group(
242+
obj, _format_addresses(parsed_args.address))
243+
244+
245+
class ShowAddressGroup(command.ShowOne):
246+
_description = _("Display address group details")
247+
248+
def get_parser(self, prog_name):
249+
parser = super(ShowAddressGroup, self).get_parser(prog_name)
250+
parser.add_argument(
251+
'address_group',
252+
metavar="<address-group>",
253+
help=_("Address group to display (name or ID)")
254+
)
255+
256+
return parser
257+
258+
def take_action(self, parsed_args):
259+
client = self.app.client_manager.network
260+
obj = client.find_address_group(
261+
parsed_args.address_group,
262+
ignore_missing=False)
263+
display_columns, columns = _get_columns(obj)
264+
data = utils.get_item_properties(obj, columns, formatters={})
265+
266+
return (display_columns, data)
267+
268+
269+
class UnsetAddressGroup(command.Command):
270+
_description = _("Unset address group properties")
271+
272+
def get_parser(self, prog_name):
273+
parser = super(UnsetAddressGroup, self).get_parser(prog_name)
274+
parser.add_argument(
275+
'address_group',
276+
metavar="<address-group>",
277+
help=_("Address group to modify (name or ID)")
278+
)
279+
parser.add_argument(
280+
"--address",
281+
metavar="<ip-address>",
282+
action='append',
283+
default=[],
284+
help=_("IP address or CIDR "
285+
"(repeat option to unset multiple addresses)"),
286+
)
287+
return parser
288+
289+
def take_action(self, parsed_args):
290+
client = self.app.client_manager.network
291+
obj = client.find_address_group(
292+
parsed_args.address_group,
293+
ignore_missing=False)
294+
if parsed_args.address:
295+
client.remove_addresses_from_address_group(
296+
obj, _format_addresses(parsed_args.address))

0 commit comments

Comments
 (0)