Skip to content

Commit 3e621c9

Browse files
Jenkinsopenstack-gerrit
authored andcommitted
Merge "Introduce Neutron DHCP agent commands to OSC"
2 parents f16513a + f4fd8f6 commit 3e621c9

10 files changed

Lines changed: 456 additions & 23 deletions

File tree

doc/source/command-objects/network-agent.rst

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,31 @@ agent is "True".
1010

1111
Network v2
1212

13+
network agent add network
14+
-------------------------
15+
16+
Add network to an agent
17+
18+
.. program:: network agent add network
19+
.. code:: bash
20+
21+
openstack network agent add network
22+
[--dhcp]
23+
<agent-id>
24+
<network>
25+
26+
.. describe:: --dhcp
27+
28+
Add a network to DHCP agent.
29+
30+
.. describe:: <agent-id>
31+
32+
Agent to which a network is added. (ID only)
33+
34+
.. describe:: <network>
35+
36+
Network to be added to an agent. (ID or name)
37+
1338
network agent delete
1439
--------------------
1540

@@ -37,6 +62,7 @@ List network agents
3762
openstack network agent list
3863
[--agent-type <agent-type>]
3964
[--host <host>]
65+
[--network <network>]
4066
4167
.. option:: --agent-type <agent-type>
4268

@@ -49,6 +75,10 @@ List network agents
4975

5076
List only agents running on the specified host
5177

78+
.. option:: --network <network>
79+
80+
List agents hosting a network. (ID or name)
81+
5282
network agent set
5383
-----------------
5484

@@ -94,3 +124,28 @@ Display network agent details
94124
.. describe:: <network-agent>
95125

96126
Network agent to display (ID only)
127+
128+
network agent remove network
129+
----------------------------
130+
131+
Remove network from an agent
132+
133+
.. program:: network agent remove network
134+
.. code:: bash
135+
136+
openstack network agent remove network
137+
[--dhcp]
138+
<agent-id>
139+
<network>
140+
141+
.. describe:: --dhcp
142+
143+
Remove network from DHCP agent.
144+
145+
.. describe:: <agent-id>
146+
147+
Agent to which a network is removed. (ID only)
148+
149+
.. describe:: <network>
150+
151+
Network to be removed from an agent. (ID or name)

doc/source/command-objects/network.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ List networks
203203
[--provider-network-type <provider-network-type>]
204204
[--provider-physical-network <provider-physical-network>]
205205
[--provider-segment <provider-segment>]
206+
[--agent <agent-id>]
206207
207208
.. option:: --external
208209
@@ -290,6 +291,10 @@ List networks
290291
291292
*Network version 2 only*
292293
294+
.. option:: --agent <agent-id>
295+
296+
List networks hosted by agent (ID only)
297+
293298
network set
294299
-----------
295300

openstackclient/network/v2/network.py

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,10 @@ def _get_network_columns(item):
6060

6161

6262
def _get_columns(item):
63-
columns = list(item.keys())
64-
if 'tenant_id' in columns:
65-
columns.remove('tenant_id')
66-
if 'project_id' not in columns:
67-
columns.append('project_id')
68-
return tuple(sorted(columns))
63+
column_map = {
64+
'tenant_id': 'project_id',
65+
}
66+
return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
6967

7068

7169
def _get_attrs(client_manager, parsed_args):
@@ -305,9 +303,9 @@ def take_action_network(self, client, parsed_args):
305303
def take_action_compute(self, client, parsed_args):
306304
attrs = _get_attrs_compute(self.app.client_manager, parsed_args)
307305
obj = client.networks.create(**attrs)
308-
columns = _get_columns(obj._info)
306+
display_columns, columns = _get_columns(obj._info)
309307
data = utils.get_dict_properties(obj._info, columns)
310-
return (columns, data)
308+
return (display_columns, data)
311309

312310

313311
class DeleteNetwork(common.NetworkAndComputeDelete):
@@ -420,7 +418,11 @@ def update_parser_network(self, parser):
420418
help=_("List networks according to VLAN ID for VLAN networks "
421419
"or Tunnel ID for GENEVE/GRE/VXLAN networks")
422420
)
423-
421+
parser.add_argument(
422+
'--agent',
423+
metavar='<agent-id>',
424+
dest='agent_id',
425+
help=_('List networks hosted by agent (ID only)'))
424426
return parser
425427

426428
def take_action_network(self, client, parsed_args):
@@ -450,6 +452,26 @@ def take_action_network(self, client, parsed_args):
450452
'Router Type',
451453
'Availability Zones',
452454
)
455+
elif parsed_args.agent_id:
456+
columns = (
457+
'id',
458+
'name',
459+
'subnet_ids'
460+
)
461+
column_headers = (
462+
'ID',
463+
'Name',
464+
'Subnets',
465+
)
466+
client = self.app.client_manager.network
467+
dhcp_agent = client.get_agent(parsed_args.agent_id)
468+
data = client.dhcp_agent_hosting_networks(dhcp_agent)
469+
470+
return (column_headers,
471+
(utils.get_item_properties(
472+
s, columns,
473+
formatters=_formatters,
474+
) for s in data))
453475
else:
454476
columns = (
455477
'id',
@@ -665,6 +687,6 @@ def take_action_compute(self, client, parsed_args):
665687
client.networks,
666688
parsed_args.network,
667689
)
668-
columns = _get_columns(obj._info)
690+
display_columns, columns = _get_columns(obj._info)
669691
data = utils.get_dict_properties(obj._info, columns)
670-
return (columns, data)
692+
return (display_columns, data)

openstackclient/network/v2/network_agent.py

Lines changed: 105 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
def _format_admin_state(state):
3030
return 'UP' if state else 'DOWN'
3131

32-
3332
_formatters = {
3433
'admin_state_up': _format_admin_state,
3534
'is_admin_state_up': _format_admin_state,
@@ -45,6 +44,40 @@ def _get_network_columns(item):
4544
return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
4645

4746

47+
class AddNetworkToAgent(command.Command):
48+
_description = _("Add network to an agent")
49+
50+
def get_parser(self, prog_name):
51+
parser = super(AddNetworkToAgent, self).get_parser(prog_name)
52+
parser.add_argument(
53+
'--dhcp',
54+
action='store_true',
55+
help=_('Add network to a DHCP agent'))
56+
parser.add_argument(
57+
'agent_id',
58+
metavar='<agent-id>',
59+
help=_('Agent to which a network is added. (ID only)'))
60+
parser.add_argument(
61+
'network',
62+
metavar='<network>',
63+
help=_('Network to be added to an agent. (ID or name)'))
64+
65+
return parser
66+
67+
def take_action(self, parsed_args):
68+
client = self.app.client_manager.network
69+
agent = client.get_agent(parsed_args.agent_id)
70+
if parsed_args.dhcp:
71+
network = client.find_network(
72+
parsed_args.network, ignore_missing=False)
73+
try:
74+
client.add_dhcp_agent_to_network(agent, network)
75+
except Exception:
76+
msg = 'Failed to add {} to {}'.format(
77+
network.name, agent.agent_type)
78+
exceptions.CommandError(msg)
79+
80+
4881
class DeleteNetworkAgent(command.Command):
4982
_description = _("Delete network agent(s)")
5083

@@ -102,6 +135,11 @@ def get_parser(self, prog_name):
102135
metavar='<host>',
103136
help=_("List only agents running on the specified host")
104137
)
138+
parser.add_argument(
139+
'--network',
140+
metavar='<network>',
141+
help=_('List agents hosting a network (name or ID)')
142+
)
105143
return parser
106144

107145
def take_action(self, parsed_args):
@@ -140,16 +178,72 @@ def take_action(self, parsed_args):
140178
}
141179

142180
filters = {}
143-
if parsed_args.agent_type is not None:
144-
filters['agent_type'] = key_value[parsed_args.agent_type]
145-
if parsed_args.host is not None:
146-
filters['host'] = parsed_args.host
147-
148-
data = client.agents(**filters)
149-
return (column_headers,
150-
(utils.get_item_properties(
151-
s, columns, formatters=_formatters,
152-
) for s in data))
181+
if parsed_args.network is not None:
182+
columns = (
183+
'id',
184+
'host',
185+
'is_admin_state_up',
186+
'is_alive',
187+
)
188+
column_headers = (
189+
'ID',
190+
'Host',
191+
'Admin State Up',
192+
'Alive',
193+
)
194+
network = client.find_network(
195+
parsed_args.network, ignore_missing=False)
196+
data = client.network_hosting_dhcp_agents(network)
197+
198+
return (column_headers,
199+
(utils.get_item_properties(
200+
s, columns,
201+
formatters=_formatters,
202+
) for s in data))
203+
else:
204+
if parsed_args.agent_type is not None:
205+
filters['agent_type'] = key_value[parsed_args.agent_type]
206+
if parsed_args.host is not None:
207+
filters['host'] = parsed_args.host
208+
209+
data = client.agents(**filters)
210+
return (column_headers,
211+
(utils.get_item_properties(
212+
s, columns, formatters=_formatters,
213+
) for s in data))
214+
215+
216+
class RemoveNetworkFromAgent(command.Command):
217+
_description = _("Remove network from an agent.")
218+
219+
def get_parser(self, prog_name):
220+
parser = super(RemoveNetworkFromAgent, self).get_parser(prog_name)
221+
parser.add_argument(
222+
'--dhcp',
223+
action='store_true',
224+
help=_('Remove network from DHCP agent'))
225+
parser.add_argument(
226+
'agent_id',
227+
metavar='<agent-id>',
228+
help=_('Agent to which a network is removed. (ID only)'))
229+
parser.add_argument(
230+
'network',
231+
metavar='<network>',
232+
help=_('Network to be removed from an agent. (ID or name)'))
233+
return parser
234+
235+
def take_action(self, parsed_args):
236+
client = self.app.client_manager.network
237+
agent = client.get_agent(parsed_args.agent_id)
238+
if parsed_args.dhcp:
239+
network = client.find_network(
240+
parsed_args.network, ignore_missing=False)
241+
try:
242+
client.remove_dhcp_agent_from_network(agent, network)
243+
except Exception:
244+
msg = 'Failed to remove {} to {}'.format(
245+
network.name, agent.agent_type)
246+
exceptions.CommandError(msg)
153247

154248

155249
# TODO(huanxuan): Use the SDK resource mapped attribute names once the

openstackclient/tests/functional/network/v2/test_network.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,49 @@ def test_network_list(self):
238238
self.assertIn(name1, col_name)
239239
self.assertNotIn(name2, col_name)
240240

241+
def test_network_dhcp_agent(self):
242+
name1 = uuid.uuid4().hex
243+
cmd_output1 = json.loads(self.openstack(
244+
'network create -f json ' +
245+
'--description aaaa ' +
246+
name1
247+
))
248+
249+
self.addCleanup(self.openstack, 'network delete ' + name1)
250+
251+
# Get network ID
252+
network_id = cmd_output1['id']
253+
254+
# Get DHCP Agent ID
255+
cmd_output2 = json.loads(self.openstack(
256+
'network agent list -f json --agent-type dhcp'
257+
))
258+
agent_id = cmd_output2[0]['ID']
259+
260+
# Add Agent to Network
261+
self.openstack(
262+
'network agent add network --dhcp '
263+
+ agent_id + ' ' + network_id
264+
)
265+
266+
# Test network list --agent
267+
cmd_output3 = json.loads(self.openstack(
268+
'network list -f json --agent ' + agent_id
269+
))
270+
271+
# Cleanup
272+
# Remove Agent from Network
273+
self.openstack(
274+
'network agent remove network --dhcp '
275+
+ agent_id + ' ' + network_id
276+
)
277+
278+
# Assert
279+
col_name = [x["ID"] for x in cmd_output3]
280+
self.assertIn(
281+
network_id, col_name
282+
)
283+
241284
def test_network_set(self):
242285
"""Tests create options, set, show, delete"""
243286
name = uuid.uuid4().hex

0 commit comments

Comments
 (0)