summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/network/v2/network.py44
-rw-r--r--openstackclient/network/v2/network_agent.py116
-rw-r--r--openstackclient/tests/functional/network/v2/test_network.py43
-rw-r--r--openstackclient/tests/functional/network/v2/test_network_agent.py52
-rw-r--r--openstackclient/tests/unit/network/v2/test_network.py26
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_agent.py129
6 files changed, 387 insertions, 23 deletions
diff --git a/openstackclient/network/v2/network.py b/openstackclient/network/v2/network.py
index 3aa8ec84..3e0bb776 100644
--- a/openstackclient/network/v2/network.py
+++ b/openstackclient/network/v2/network.py
@@ -60,12 +60,10 @@ def _get_network_columns(item):
def _get_columns(item):
- columns = list(item.keys())
- if 'tenant_id' in columns:
- columns.remove('tenant_id')
- if 'project_id' not in columns:
- columns.append('project_id')
- return tuple(sorted(columns))
+ column_map = {
+ 'tenant_id': 'project_id',
+ }
+ return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
def _get_attrs(client_manager, parsed_args):
@@ -305,9 +303,9 @@ class CreateNetwork(common.NetworkAndComputeShowOne):
def take_action_compute(self, client, parsed_args):
attrs = _get_attrs_compute(self.app.client_manager, parsed_args)
obj = client.networks.create(**attrs)
- columns = _get_columns(obj._info)
+ display_columns, columns = _get_columns(obj._info)
data = utils.get_dict_properties(obj._info, columns)
- return (columns, data)
+ return (display_columns, data)
class DeleteNetwork(common.NetworkAndComputeDelete):
@@ -420,7 +418,11 @@ class ListNetwork(common.NetworkAndComputeLister):
help=_("List networks according to VLAN ID for VLAN networks "
"or Tunnel ID for GENEVE/GRE/VXLAN networks")
)
-
+ parser.add_argument(
+ '--agent',
+ metavar='<agent-id>',
+ dest='agent_id',
+ help=_('List networks hosted by agent (ID only)'))
return parser
def take_action_network(self, client, parsed_args):
@@ -450,6 +452,26 @@ class ListNetwork(common.NetworkAndComputeLister):
'Router Type',
'Availability Zones',
)
+ elif parsed_args.agent_id:
+ columns = (
+ 'id',
+ 'name',
+ 'subnet_ids'
+ )
+ column_headers = (
+ 'ID',
+ 'Name',
+ 'Subnets',
+ )
+ client = self.app.client_manager.network
+ dhcp_agent = client.get_agent(parsed_args.agent_id)
+ data = client.dhcp_agent_hosting_networks(dhcp_agent)
+
+ return (column_headers,
+ (utils.get_item_properties(
+ s, columns,
+ formatters=_formatters,
+ ) for s in data))
else:
columns = (
'id',
@@ -665,6 +687,6 @@ class ShowNetwork(common.NetworkAndComputeShowOne):
client.networks,
parsed_args.network,
)
- columns = _get_columns(obj._info)
+ display_columns, columns = _get_columns(obj._info)
data = utils.get_dict_properties(obj._info, columns)
- return (columns, data)
+ return (display_columns, data)
diff --git a/openstackclient/network/v2/network_agent.py b/openstackclient/network/v2/network_agent.py
index d429fa08..c23d3e8b 100644
--- a/openstackclient/network/v2/network_agent.py
+++ b/openstackclient/network/v2/network_agent.py
@@ -29,7 +29,6 @@ LOG = logging.getLogger(__name__)
def _format_admin_state(state):
return 'UP' if state else 'DOWN'
-
_formatters = {
'admin_state_up': _format_admin_state,
'is_admin_state_up': _format_admin_state,
@@ -45,6 +44,40 @@ def _get_network_columns(item):
return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
+class AddNetworkToAgent(command.Command):
+ _description = _("Add network to an agent")
+
+ def get_parser(self, prog_name):
+ parser = super(AddNetworkToAgent, self).get_parser(prog_name)
+ parser.add_argument(
+ '--dhcp',
+ action='store_true',
+ help=_('Add network to a DHCP agent'))
+ parser.add_argument(
+ 'agent_id',
+ metavar='<agent-id>',
+ help=_('Agent to which a network is added. (ID only)'))
+ parser.add_argument(
+ 'network',
+ metavar='<network>',
+ help=_('Network to be added to an agent. (ID or name)'))
+
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ agent = client.get_agent(parsed_args.agent_id)
+ if parsed_args.dhcp:
+ network = client.find_network(
+ parsed_args.network, ignore_missing=False)
+ try:
+ client.add_dhcp_agent_to_network(agent, network)
+ except Exception:
+ msg = 'Failed to add {} to {}'.format(
+ network.name, agent.agent_type)
+ exceptions.CommandError(msg)
+
+
class DeleteNetworkAgent(command.Command):
_description = _("Delete network agent(s)")
@@ -101,6 +134,11 @@ class ListNetworkAgent(command.Lister):
metavar='<host>',
help=_("List only agents running on the specified host")
)
+ parser.add_argument(
+ '--network',
+ metavar='<network>',
+ help=_('List agents hosting a network (name or ID)')
+ )
return parser
def take_action(self, parsed_args):
@@ -138,16 +176,72 @@ class ListNetworkAgent(command.Lister):
}
filters = {}
- if parsed_args.agent_type is not None:
- filters['agent_type'] = key_value[parsed_args.agent_type]
- if parsed_args.host is not None:
- filters['host'] = parsed_args.host
-
- data = client.agents(**filters)
- return (column_headers,
- (utils.get_item_properties(
- s, columns, formatters=_formatters,
- ) for s in data))
+ if parsed_args.network is not None:
+ columns = (
+ 'id',
+ 'host',
+ 'is_admin_state_up',
+ 'is_alive',
+ )
+ column_headers = (
+ 'ID',
+ 'Host',
+ 'Admin State Up',
+ 'Alive',
+ )
+ network = client.find_network(
+ parsed_args.network, ignore_missing=False)
+ data = client.network_hosting_dhcp_agents(network)
+
+ return (column_headers,
+ (utils.get_item_properties(
+ s, columns,
+ formatters=_formatters,
+ ) for s in data))
+ else:
+ if parsed_args.agent_type is not None:
+ filters['agent_type'] = key_value[parsed_args.agent_type]
+ if parsed_args.host is not None:
+ filters['host'] = parsed_args.host
+
+ data = client.agents(**filters)
+ return (column_headers,
+ (utils.get_item_properties(
+ s, columns, formatters=_formatters,
+ ) for s in data))
+
+
+class RemoveNetworkFromAgent(command.Command):
+ _description = _("Remove network from an agent.")
+
+ def get_parser(self, prog_name):
+ parser = super(RemoveNetworkFromAgent, self).get_parser(prog_name)
+ parser.add_argument(
+ '--dhcp',
+ action='store_true',
+ help=_('Remove network from DHCP agent'))
+ parser.add_argument(
+ 'agent_id',
+ metavar='<agent-id>',
+ help=_('Agent to which a network is removed. (ID only)'))
+ parser.add_argument(
+ 'network',
+ metavar='<network>',
+ help=_('Network to be removed from an agent. (ID or name)'))
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ agent = client.get_agent(parsed_args.agent_id)
+ if parsed_args.dhcp:
+ network = client.find_network(
+ parsed_args.network, ignore_missing=False)
+ try:
+ client.remove_dhcp_agent_from_network(agent, network)
+ except Exception:
+ msg = 'Failed to remove {} to {}'.format(
+ network.name, agent.agent_type)
+ exceptions.CommandError(msg)
# TODO(huanxuan): Use the SDK resource mapped attribute names once the
diff --git a/openstackclient/tests/functional/network/v2/test_network.py b/openstackclient/tests/functional/network/v2/test_network.py
index 12636558..0e10bfce 100644
--- a/openstackclient/tests/functional/network/v2/test_network.py
+++ b/openstackclient/tests/functional/network/v2/test_network.py
@@ -238,6 +238,49 @@ class NetworkTests(base.TestCase):
self.assertIn(name1, col_name)
self.assertNotIn(name2, col_name)
+ def test_network_dhcp_agent(self):
+ name1 = uuid.uuid4().hex
+ cmd_output1 = json.loads(self.openstack(
+ 'network create -f json ' +
+ '--description aaaa ' +
+ name1
+ ))
+
+ self.addCleanup(self.openstack, 'network delete ' + name1)
+
+ # Get network ID
+ network_id = cmd_output1['id']
+
+ # Get DHCP Agent ID
+ cmd_output2 = json.loads(self.openstack(
+ 'network agent list -f json --agent-type dhcp'
+ ))
+ agent_id = cmd_output2[0]['ID']
+
+ # Add Agent to Network
+ self.openstack(
+ 'network agent add network --dhcp '
+ + agent_id + ' ' + network_id
+ )
+
+ # Test network list --agent
+ cmd_output3 = json.loads(self.openstack(
+ 'network list -f json --agent ' + agent_id
+ ))
+
+ # Cleanup
+ # Remove Agent from Network
+ self.openstack(
+ 'network agent remove network --dhcp '
+ + agent_id + ' ' + network_id
+ )
+
+ # Assert
+ col_name = [x["ID"] for x in cmd_output3]
+ self.assertIn(
+ network_id, col_name
+ )
+
def test_network_set(self):
"""Tests create options, set, show, delete"""
name = uuid.uuid4().hex
diff --git a/openstackclient/tests/functional/network/v2/test_network_agent.py b/openstackclient/tests/functional/network/v2/test_network_agent.py
index dd6112e7..6da721d1 100644
--- a/openstackclient/tests/functional/network/v2/test_network_agent.py
+++ b/openstackclient/tests/functional/network/v2/test_network_agent.py
@@ -10,6 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+import json
+import uuid
+
from openstackclient.tests.functional import base
@@ -39,3 +42,52 @@ class NetworkAgentTests(base.TestCase):
self.openstack('network agent set --enable ' + self.IDs[0])
raw_output = self.openstack('network agent show ' + self.IDs[0] + opts)
self.assertEqual("UP\n", raw_output)
+
+
+class NetworkAgentListTests(base.TestCase):
+ """Functional test for network agent list --network. """
+
+ def test_network_dhcp_agent_list(self):
+ """Test network agent list"""
+
+ name1 = uuid.uuid4().hex
+ cmd_output1 = json.loads(self.openstack(
+ 'network create -f json ' +
+ '--description aaaa ' +
+ name1
+ ))
+
+ self.addCleanup(self.openstack, 'network delete ' + name1)
+
+ # Get network ID
+ network_id = cmd_output1['id']
+
+ # Get DHCP Agent ID
+ cmd_output2 = json.loads(self.openstack(
+ 'network agent list -f json --agent-type dhcp'
+ ))
+ agent_id = cmd_output2[0]['ID']
+
+ # Add Agent to Network
+ self.openstack(
+ 'network agent add network --dhcp '
+ + agent_id + ' ' + network_id
+ )
+
+ # Test network agent list --network
+ cmd_output3 = json.loads(self.openstack(
+ 'network agent list -f json --network ' + network_id
+ ))
+
+ # Cleanup
+ # Remove Agent from Network
+ self.openstack(
+ 'network agent remove network --dhcp '
+ + agent_id + ' ' + network_id
+ )
+
+ # Assert
+ col_name = [x["ID"] for x in cmd_output3]
+ self.assertIn(
+ agent_id, col_name
+ )
diff --git a/openstackclient/tests/unit/network/v2/test_network.py b/openstackclient/tests/unit/network/v2/test_network.py
index b405bef9..bc1279ec 100644
--- a/openstackclient/tests/unit/network/v2/test_network.py
+++ b/openstackclient/tests/unit/network/v2/test_network.py
@@ -491,6 +491,13 @@ class TestListNetwork(TestNetwork):
self.network.networks = mock.Mock(return_value=self._network)
+ self._agent = \
+ network_fakes.FakeNetworkAgent.create_one_network_agent()
+ self.network.get_agent = mock.Mock(return_value=self._agent)
+
+ self.network.dhcp_agent_hosting_networks = mock.Mock(
+ return_value=self._network)
+
def test_network_list_no_options(self):
arglist = []
verifylist = [
@@ -765,6 +772,25 @@ class TestListNetwork(TestNetwork):
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
+ def test_network_list_dhcp_agent(self):
+ arglist = [
+ '--agent', self._agent.id
+ ]
+ verifylist = [
+ ('agent_id', self._agent.id),
+ ]
+
+ attrs = {self._agent, }
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.dhcp_agent_hosting_networks.assert_called_once_with(
+ *attrs)
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(list(data), list(self.data))
+
class TestSetNetwork(TestNetwork):
diff --git a/openstackclient/tests/unit/network/v2/test_network_agent.py b/openstackclient/tests/unit/network/v2/test_network_agent.py
index 2fc0c043..0d741e06 100644
--- a/openstackclient/tests/unit/network/v2/test_network_agent.py
+++ b/openstackclient/tests/unit/network/v2/test_network_agent.py
@@ -31,6 +31,48 @@ class TestNetworkAgent(network_fakes.TestNetworkV2):
self.network = self.app.client_manager.network
+class TestAddNetworkToAgent(TestNetworkAgent):
+
+ net = network_fakes.FakeNetwork.create_one_network()
+ agent = network_fakes.FakeNetworkAgent.create_one_network_agent()
+
+ def setUp(self):
+ super(TestAddNetworkToAgent, self).setUp()
+
+ self.network.get_agent = mock.Mock(return_value=self.agent)
+ self.network.find_network = mock.Mock(return_value=self.net)
+ self.network.name = self.network.find_network.name
+ self.network.add_dhcp_agent_to_network = mock.Mock()
+ self.cmd = network_agent.AddNetworkToAgent(
+ self.app, self.namespace)
+
+ def test_show_no_options(self):
+ arglist = []
+ verifylist = []
+
+ # Missing required args should bail here
+ self.assertRaises(tests_utils.ParserException, self.check_parser,
+ self.cmd, arglist, verifylist)
+
+ def test_add_network_to_dhcp_agent(self):
+ arglist = [
+ '--dhcp',
+ self.agent.id,
+ self.net.id
+ ]
+ verifylist = [
+ ('dhcp', True),
+ ('agent_id', self.agent.id),
+ ('network', self.net.id),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.cmd.take_action(parsed_args)
+
+ self.network.add_dhcp_agent_to_network.assert_called_once_with(
+ self.agent, self.net)
+
+
class TestDeleteNetworkAgent(TestNetworkAgent):
network_agents = (
@@ -66,7 +108,6 @@ class TestDeleteNetworkAgent(TestNetworkAgent):
def test_multi_network_agents_delete(self):
arglist = []
- verifylist = []
for n in self.network_agents:
arglist.append(n.id)
@@ -141,11 +182,37 @@ class TestListNetworkAgent(TestNetworkAgent):
agent.binary,
))
+ network_agent_columns = (
+ 'ID',
+ 'Host',
+ 'Admin State Up',
+ 'Alive',
+ )
+
+ network_agent_data = []
+
+ for agent in network_agents:
+ network_agent_data.append((
+ agent.id,
+ agent.host,
+ network_agent._format_admin_state(agent.admin_state_up),
+ agent.alive,
+ ))
+
def setUp(self):
super(TestListNetworkAgent, self).setUp()
self.network.agents = mock.Mock(
return_value=self.network_agents)
+ _testagent = \
+ network_fakes.FakeNetworkAgent.create_one_network_agent()
+ self.network.get_agent = mock.Mock(return_value=_testagent)
+
+ self._testnetwork = network_fakes.FakeNetwork.create_one_network()
+ self.network.find_network = mock.Mock(return_value=self._testnetwork)
+ self.network.network_hosting_dhcp_agents = mock.Mock(
+ return_value=self.network_agents)
+
# Get the command object to test
self.cmd = network_agent.ListNetworkAgent(self.app, self.namespace)
@@ -194,6 +261,66 @@ class TestListNetworkAgent(TestNetworkAgent):
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, list(data))
+ def test_network_agents_list_networks(self):
+ arglist = [
+ '--network', self._testnetwork.id,
+ ]
+ verifylist = [
+ ('network', self._testnetwork.id),
+ ]
+
+ attrs = {self._testnetwork, }
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.network.network_hosting_dhcp_agents.assert_called_once_with(
+ *attrs)
+ self.assertEqual(self.network_agent_columns, columns)
+ self.assertEqual(list(self.network_agent_data), list(data))
+
+
+class TestRemoveNetworkFromAgent(TestNetworkAgent):
+
+ net = network_fakes.FakeNetwork.create_one_network()
+ agent = network_fakes.FakeNetworkAgent.create_one_network_agent()
+
+ def setUp(self):
+ super(TestRemoveNetworkFromAgent, self).setUp()
+
+ self.network.get_agent = mock.Mock(return_value=self.agent)
+ self.network.find_network = mock.Mock(return_value=self.net)
+ self.network.name = self.network.find_network.name
+ self.network.remove_dhcp_agent_from_network = mock.Mock()
+ self.cmd = network_agent.RemoveNetworkFromAgent(
+ self.app, self.namespace)
+
+ def test_show_no_options(self):
+ arglist = []
+ verifylist = []
+
+ # Missing required args should bail here
+ self.assertRaises(tests_utils.ParserException, self.check_parser,
+ self.cmd, arglist, verifylist)
+
+ def test_network_from_dhcp_agent(self):
+ arglist = [
+ '--dhcp',
+ self.agent.id,
+ self.net.id
+ ]
+ verifylist = [
+ ('dhcp', True),
+ ('agent_id', self.agent.id),
+ ('network', self.net.id),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.cmd.take_action(parsed_args)
+
+ self.network.remove_dhcp_agent_from_network.assert_called_once_with(
+ self.agent, self.net)
+
# TODO(huanxuan): Also update by the new attribute name
# "is_admin_state_up" after sdk 0.9.12