Sophie

Sophie

distrib > Fedora > 18 > i386 > by-pkgid > 0305113317f9e80328b139dce3f45533 > files > 17

python-quantumclient-2.1-1.fc18.src.rpm

From f288e2a2f9ce9bfd175477086c225f04a1cf6cc2 Mon Sep 17 00:00:00 2001
From: Akihiro MOTOKI <motoki@da.jp.nec.com>
Date: Thu, 10 Jan 2013 03:22:14 +0900
Subject: [PATCH] Display subnet cidr information in net-list

Fixes bug 1074415

This commit introduces extend_list() in ListCommand class. This method
can be used to update a retrieved list (e.g., add additional information
or convert some field to more human-readable value).

Change-Id: Icf5ab616ab4d9add16c921e1944ba37b376b2ab2
---
 quantumclient/quantum/v2_0/__init__.py         |  30 ++++++--
 quantumclient/quantum/v2_0/network.py          |  24 ++++--
 quantumclient/tests/unit/test_cli20_network.py | 101 +++++++++++++++++++++----
 3 files changed, 127 insertions(+), 28 deletions(-)

diff --git a/quantumclient/quantum/v2_0/__init__.py b/quantumclient/quantum/v2_0/__init__.py
index 5eae661..530b07a 100644
--- a/quantumclient/quantum/v2_0/__init__.py
+++ b/quantumclient/quantum/v2_0/__init__.py
@@ -375,7 +375,7 @@ class DeleteCommand(QuantumCommand):
 
 
 class ListCommand(QuantumCommand, lister.Lister):
-    """List resourcs that belong to a given tenant
+    """List resources that belong to a given tenant
 
     """
 
@@ -391,11 +391,10 @@ class ListCommand(QuantumCommand, lister.Lister):
         add_extra_argument(parser, 'filter_specs', 'filters options')
         return parser
 
-    def get_data(self, parsed_args):
-        self.log.debug('get_data(%s)' % parsed_args)
+    def retrieve_list(self, parsed_args):
+        """Retrieve a list of resources from Quantum server"""
         quantum_client = self.get_client()
         search_opts = parse_args_to_dict(parsed_args.filter_specs)
-
         self.log.debug('search options: %s', search_opts)
         quantum_client.format = parsed_args.request_format
         fields = parsed_args.fields
@@ -411,12 +410,21 @@ class ListCommand(QuantumCommand, lister.Lister):
             search_opts.update({'verbose': 'True'})
         obj_lister = getattr(quantum_client,
                              "list_%ss" % self.resource)
-
         data = obj_lister(**search_opts)
-        info = []
+
         collection = self.resource + "s"
-        if collection in data:
-            info = data[collection]
+        return data.get(collection, [])
+
+    def extend_list(self, data, parsed_args):
+        """Update a retrieved list.
+
+        This method provides a way to modify a original list returned from
+        the quantum server. For example, you can add subnet cidr information
+        to a list network.
+        """
+        pass
+
+    def setup_columns(self, info, parsed_args):
         _columns = len(info) > 0 and sorted(info[0].keys()) or []
         if not _columns:
             # clean the parsed_args.columns so that cliff will not break
@@ -432,6 +440,12 @@ class ListCommand(QuantumCommand, lister.Lister):
             s, _columns, formatters=self._formatters, )
             for s in info), )
 
+    def get_data(self, parsed_args):
+        self.log.debug('get_data(%s)' % parsed_args)
+        data = self.retrieve_list(parsed_args)
+        self.extend_list(data, parsed_args)
+        return self.setup_columns(data, parsed_args)
+
 
 class ShowCommand(QuantumCommand, show.ShowOne):
     """Show information of a given resource
diff --git a/quantumclient/quantum/v2_0/network.py b/quantumclient/quantum/v2_0/network.py
index 4d88ab3..b714ae5 100644
--- a/quantumclient/quantum/v2_0/network.py
+++ b/quantumclient/quantum/v2_0/network.py
@@ -18,6 +18,7 @@
 import argparse
 import logging
 
+from quantumclient.common import utils
 from quantumclient.quantum.v2_0 import CreateCommand
 from quantumclient.quantum.v2_0 import DeleteCommand
 from quantumclient.quantum.v2_0 import ListCommand
@@ -27,7 +28,8 @@ from quantumclient.quantum.v2_0 import UpdateCommand
 
 def _format_subnets(network):
     try:
-        return '\n'.join(network['subnets'])
+        return '\n'.join([' '.join([s['id'], s.get('cidr', '')])
+                          for s in network['subnets']])
     except Exception:
         return ''
 
@@ -40,20 +42,28 @@ class ListNetwork(ListCommand):
     _formatters = {'subnets': _format_subnets, }
     list_columns = ['id', 'name', 'subnets']
 
+    def extend_list(self, data, parsed_args):
+        """Add subnet information to a network list"""
+        quantum_client = self.get_client()
+        search_opts = {'fields': ['id', 'cidr']}
+        subnets = quantum_client.list_subnets(**search_opts).get('subnets', [])
+        subnet_dict = dict([(s['id'], s) for s in subnets])
+        for n in data:
+            if 'subnets' in n:
+                n['subnets'] = [(subnet_dict.get(s) or {"id": s})
+                                for s in n['subnets']]
 
-class ListExternalNetwork(ListCommand):
+
+class ListExternalNetwork(ListNetwork):
     """List external networks that belong to a given tenant"""
 
-    resource = 'network'
     log = logging.getLogger(__name__ + '.ListExternalNetwork')
-    _formatters = {'subnets': _format_subnets, }
-    list_colums = ['id', 'name', 'subnets']
 
-    def get_data(self, parsed_args):
+    def retrieve_list(self, parsed_args):
         if '--' not in parsed_args.filter_specs:
             parsed_args.filter_specs.append('--')
         parsed_args.filter_specs.append('--router:external=True')
-        return super(ListExternalNetwork, self).get_data(parsed_args)
+        return super(ListExternalNetwork, self).retrieve_list(parsed_args)
 
 
 class ShowNetwork(ShowCommand):
diff --git a/quantumclient/tests/unit/test_cli20_network.py b/quantumclient/tests/unit/test_cli20_network.py
index 1ef0215..8eebcfe 100644
--- a/quantumclient/tests/unit/test_cli20_network.py
+++ b/quantumclient/tests/unit/test_cli20_network.py
@@ -17,7 +17,8 @@
 
 import sys
 
-from mox import ContainsKeyValue
+import mox
+from mox import (ContainsKeyValue, IgnoreArg, IsA)
 
 from quantumclient.common import exceptions
 from quantumclient.common import utils
@@ -101,6 +102,8 @@ class CLITestV20Network(CLITestV20Base):
         cmd = ListNetwork(MyApp(sys.stdout), None)
         self.mox.StubOutWithMock(cmd, "get_client")
         self.mox.StubOutWithMock(self.client.httpclient, "request")
+        self.mox.StubOutWithMock(ListNetwork, "extend_list")
+        ListNetwork.extend_list(IsA(list), IgnoreArg())
         cmd.get_client().MultipleTimes().AndReturn(self.client)
         reses = {resources: []}
         resstr = self.client.serialize(reses)
@@ -125,40 +128,109 @@ class CLITestV20Network(CLITestV20Base):
         _str = self.fake_stdout.make_string()
         self.assertEquals('\n', _str)
 
+    def _test_list_networks(self, cmd, detail=False, tags=[],
+                            fields_1=[], fields_2=[]):
+        resources = "networks"
+        self.mox.StubOutWithMock(ListNetwork, "extend_list")
+        ListNetwork.extend_list(IsA(list), IgnoreArg())
+        self._test_list_resources(resources, cmd, detail, tags,
+                                  fields_1, fields_2)
+
     def test_list_nets_detail(self):
         """list nets: -D."""
-        resources = "networks"
         cmd = ListNetwork(MyApp(sys.stdout), None)
-        self._test_list_resources(resources, cmd, True)
+        self._test_list_networks(cmd, True)
 
     def test_list_nets_tags(self):
         """List nets: -- --tags a b."""
-        resources = "networks"
         cmd = ListNetwork(MyApp(sys.stdout), None)
-        self._test_list_resources(resources, cmd, tags=['a', 'b'])
+        self._test_list_networks(cmd, tags=['a', 'b'])
 
     def test_list_nets_detail_tags(self):
         """List nets: -D -- --tags a b."""
         resources = "networks"
         cmd = ListNetwork(MyApp(sys.stdout), None)
-        self._test_list_resources(resources, cmd, detail=True, tags=['a', 'b'])
+        self._test_list_networks(cmd, detail=True, tags=['a', 'b'])
+
+    def _test_list_nets_extend_subnets(self, data, expected):
+        def setup_list_stub(resources, data, query):
+            reses = {resources: data}
+            resstr = self.client.serialize(reses)
+            resp = (test_cli20.MyResp(200), resstr)
+            path = getattr(self.client, resources + '_path')
+            self.client.httpclient.request(
+                test_cli20.end_url(path, query), 'GET',
+                body=None,
+                headers=ContainsKeyValue(
+                    'X-Auth-Token', test_cli20.TOKEN)).AndReturn(resp)
+
+        resources = "networks"
+        cmd = ListNetwork(test_cli20.MyApp(sys.stdout), None)
+        self.mox.StubOutWithMock(cmd, 'get_client')
+        self.mox.StubOutWithMock(self.client.httpclient, 'request')
+        cmd.get_client().AndReturn(self.client)
+        setup_list_stub('networks', data, '')
+        cmd.get_client().AndReturn(self.client)
+        setup_list_stub('subnets',
+                        [{'id': 'mysubid1', 'cidr': '192.168.1.0/24'},
+                         {'id': 'mysubid2', 'cidr': '172.16.0.0/24'},
+                         {'id': 'mysubid3', 'cidr': '10.1.1.0/24'}],
+                        query='fields=id&fields=cidr')
+        self.mox.ReplayAll()
+
+        args = []
+        cmd_parser = cmd.get_parser('list_networks')
+        parsed_args = cmd_parser.parse_args(args)
+        result = cmd.get_data(parsed_args)
+        self.mox.VerifyAll()
+        self.mox.UnsetStubs()
+        _result = [x for x in result[1]]
+        self.assertEqual(len(_result), len(expected))
+        for res, exp in zip(_result, expected):
+            self.assertEqual(len(res), len(exp))
+            for a, b in zip(res, exp):
+                self.assertEqual(a, b)
+
+    def test_list_nets_extend_subnets(self):
+        data = [{'id': 'netid1', 'name': 'net1', 'subnets': ['mysubid1']},
+                {'id': 'netid2', 'name': 'net2', 'subnets': ['mysubid2',
+                                                             'mysubid3']}]
+        #             id,   name,   subnets
+        expected = [('netid1', 'net1', 'mysubid1 192.168.1.0/24'),
+                    ('netid2', 'net2',
+                     'mysubid2 172.16.0.0/24\nmysubid3 10.1.1.0/24')]
+        self._test_list_nets_extend_subnets(data, expected)
+
+    def test_list_nets_extend_subnets_no_subnet(self):
+        data = [{'id': 'netid1', 'name': 'net1', 'subnets': ['mysubid1']},
+                {'id': 'netid2', 'name': 'net2', 'subnets': ['mysubid4']}]
+        #             id,   name,   subnets
+        expected = [('netid1', 'net1', 'mysubid1 192.168.1.0/24'),
+                    ('netid2', 'net2', 'mysubid4 ')]
+        self._test_list_nets_extend_subnets(data, expected)
 
     def test_list_nets_fields(self):
         """List nets: --fields a --fields b -- --fields c d."""
         resources = "networks"
         cmd = ListNetwork(MyApp(sys.stdout), None)
-        self._test_list_resources(resources, cmd,
-                                  fields_1=['a', 'b'], fields_2=['c', 'd'])
+        self._test_list_networks(cmd,
+                                 fields_1=['a', 'b'], fields_2=['c', 'd'])
 
-    def test_list_nets_defined_column(self):
+    def _test_list_nets_columns(self, cmd, returned_body,
+                                args=['-f', 'json']):
         resources = 'networks'
+        self.mox.StubOutWithMock(ListNetwork, "extend_list")
+        ListNetwork.extend_list(IsA(list), IgnoreArg())
+        self._test_list_columns(cmd, resources, returned_body, args=args)
+
+    def test_list_nets_defined_column(self):
         cmd = ListNetwork(MyApp(sys.stdout), None)
         returned_body = {"networks": [{"name": "buildname3",
                                        "id": "id3",
                                        "tenant_id": "tenant_3",
                                        "subnets": []}]}
-        self._test_list_columns(cmd, resources, returned_body,
-                                args=['-f', 'json', '-c', 'id'])
+        self._test_list_nets_columns(cmd, returned_body,
+                                     args=['-f', 'json', '-c', 'id'])
         _str = self.fake_stdout.make_string()
         returned_networks = utils.loads(_str)
         self.assertEquals(1, len(returned_networks))
@@ -167,13 +239,12 @@ class CLITestV20Network(CLITestV20Base):
         self.assertEquals("id", network.keys()[0])
 
     def test_list_nets_with_default_column(self):
-        resources = 'networks'
         cmd = ListNetwork(MyApp(sys.stdout), None)
         returned_body = {"networks": [{"name": "buildname3",
                                        "id": "id3",
                                        "tenant_id": "tenant_3",
                                        "subnets": []}]}
-        self._test_list_columns(cmd, resources, returned_body)
+        self._test_list_nets_columns(cmd, returned_body)
         _str = self.fake_stdout.make_string()
         returned_networks = utils.loads(_str)
         self.assertEquals(1, len(returned_networks))
@@ -187,6 +258,8 @@ class CLITestV20Network(CLITestV20Base):
         cmd = ListExternalNetwork(MyApp(sys.stdout), None)
         self.mox.StubOutWithMock(cmd, "get_client")
         self.mox.StubOutWithMock(self.client.httpclient, "request")
+        self.mox.StubOutWithMock(ListNetwork, "extend_list")
+        ListNetwork.extend_list(IsA(list), IgnoreArg())
         cmd.get_client().MultipleTimes().AndReturn(self.client)
         reses = {resources: []}
         resstr = self.client.serialize(reses)
@@ -217,6 +290,8 @@ class CLITestV20Network(CLITestV20Base):
                                  fields_1=[], fields_2=[]):
         self.mox.StubOutWithMock(cmd, "get_client")
         self.mox.StubOutWithMock(self.client.httpclient, "request")
+        self.mox.StubOutWithMock(ListNetwork, "extend_list")
+        ListNetwork.extend_list(IsA(list), IgnoreArg())
         cmd.get_client().MultipleTimes().AndReturn(self.client)
         reses = {resources: [{'id': 'myid1', },
                              {'id': 'myid2', }, ], }