commit c95ff0619194b41f4bd5172329a4e4ef5463cf46
Author: Stavros Sachtouris <saxtouri@admin.grnet.gr>
Date:   Mon Nov 4 11:48:04 2013 +0200

    Pick "networking" as the name of the new client
    
    Refs: #4546

diff --git a/kamaki/clients/network/__init__.py b/kamaki/clients/network/__init__.py
deleted file mode 100644
index 804d46f..0000000
--- a/kamaki/clients/network/__init__.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2013 GRNET S.A. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-#
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-#
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from kamaki.clients import ClientError
-from kamaki.clients.network.rest_api import NetworkRestClient
-
-
-class NetworkClient(NetworkRestClient):
-    """OpenStack Network API 2.0 client"""
-
-    def list_networks(self):
-        r = self.networks_get(success=200)
-        return r.json['networks']
-
-    def create_network(self, name=None, admin_state_up=None, shared=None):
-        req = dict(network=dict(
-            name=name or '', admin_state_up=bool(admin_state_up)))
-        r = self.networks_post(json_data=req, shared=shared, success=201)
-        return r.json['network']
diff --git a/kamaki/clients/network/rest_api.py b/kamaki/clients/network/rest_api.py
deleted file mode 100644
index 0d33c58..0000000
--- a/kamaki/clients/network/rest_api.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# Copyright 2013 GRNET S.A. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-#
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-#
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from kamaki.clients import Client
-from kamaki.clients.utils import path4url
-from json import dumps
-
-
-class NetworkRestClient(Client):
-
-    def networks_get(self, network_id=None, **kwargs):
-        if network_id:
-            return self.get(path4url('networks', network_id), **kwargs)
-        return self.get(path4url('networks'), **kwargs)
-
-    def networks_post(self, json_data=None, shared=None, **kwargs):
-        path = path4url('networks')
-        self.set_param('shared', bool(shared), iff=shared)
-        return self.post(
-            path, data=dumps(json_data) if json_data else None, **kwargs)
-
-    def networks_put(
-            self, network_id,
-            json_data=None, admin_state_up=None, shared=None, **kwargs):
-        path = path4url('networks', network_id)
-
-        self.set_param(
-            'admin_state_up', bool(admin_state_up), iff=admin_state_up)
-        self.set_param('shared', bool(shared), iff=shared)
-
-        return self.put(
-            path, data=dumps(json_data) if json_data else None, **kwargs)
-
-    def networks_delete(self, network_id, **kwargs):
-        return self.delete(path4url('networks', network_id), **kwargs)
-
-    def subnets_get(self, subnet_id=None, **kwargs):
-        if subnet_id:
-            return self.get(path4url('subnets', subnet_id), **kwargs)
-        return self.get(path4url('subnets'), **kwargs)
-
-    def subnets_post(self, **kwargs):
-        return self.post(path4url('subnets'), **kwargs)
-
-    def subnets_put(self, subnet_id, **kwargs):
-        return self.put(path4url('subnets', subnet_id), **kwargs)
-
-    def subnets_delete(self, subnet_id, **kwargs):
-        return self.delete(path4url('subnets', subnet_id), **kwargs)
-
-    def ports_get(self, port_id=None, **kwargs):
-        if port_id:
-            return self.get(path4url('ports', port_id), **kwargs)
-        return self.get(path4url('ports'), **kwargs)
-
-    def ports_post(
-            self,
-            json_data=None,
-            name=None, mac_address=None, fixed_ips=None, security_groups=None,
-            **kwargs):
-        self.set_param('name', name, iff=name)
-        self.set_param('mac_address', mac_address, iff=mac_address)
-        self.set_param('fixed_ips', fixed_ips, iff=fixed_ips)
-        self.set_param('security_groups', security_groups, iff=security_groups)
-        data = dumps(json_data) if json_data else None
-        return self.post(path4url('ports'), data=data, **kwargs)
-
-    def ports_put(
-            self, port_id,
-            json_data=None,
-            name=None, mac_address=None, fixed_ips=None, security_groups=None,
-            **kwargs):
-        self.set_param('name', name, iff=name)
-        self.set_param('mac_address', mac_address, iff=mac_address)
-        self.set_param('fixed_ips', fixed_ips, iff=fixed_ips)
-        self.set_param('security_groups', security_groups, iff=security_groups)
-        data = dumps(json_data) if json_data else None
-        return self.put(path4url('ports', port_id), data=data, **kwargs)
-
-    def ports_delete(self, port_id, **kwargs):
-        return self.delete(path4url('ports', port_id), **kwargs)
diff --git a/kamaki/clients/network/test.py b/kamaki/clients/network/test.py
deleted file mode 100644
index 4a43a96..0000000
--- a/kamaki/clients/network/test.py
+++ /dev/null
@@ -1,322 +0,0 @@
-# Copyright 2013 GRNET S.A. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-#
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-#
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from mock import patch, call
-from unittest import TestCase
-from itertools import product
-from json import dumps
-
-from kamaki.clients import ClientError, network
-
-
-class NetworkRestClient(TestCase):
-
-    """Set up a ComputesRest thorough test"""
-    def setUp(self):
-        self.url = 'http://network.example.com'
-        self.token = 'n2tw0rk70k3n'
-        self.client = network.NetworkRestClient(self.url, self.token)
-
-    def tearDown(self):
-        del self.client
-
-    def _assert(self, method_call, path, set_param=None, params=(), **kwargs):
-        """Assert the REST method call is called as expected"""
-        x0 = - len(params)
-        for i, (k, v, c) in enumerate(params):
-            self.assertEqual(set_param.mock_calls[x0 + i], call(k, v, iff=c))
-
-        self.assertEqual(method_call.mock_calls[-1], call(path, **kwargs))
-
-    @patch('kamaki.clients.Client.get', return_value='ret val')
-    def test_networks_get(self, get):
-        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
-            self.assertEqual(self.client.networks_get(**kwargs), 'ret val')
-            self._assert(get, '/networks', **kwargs)
-
-            netid = 'netid'
-            self.assertEqual(
-                self.client.networks_get(network_id=netid, **kwargs),
-                'ret val')
-            self._assert(get, '/networks/%s' % netid, **kwargs)
-
-    @patch('kamaki.clients.Client.set_param')
-    @patch('kamaki.clients.Client.post', return_value='ret val')
-    def test_networks_post(self, post, set_param):
-        for params, kwargs in product(
-                (
-                    (('shared', False, None), ),
-                    (('shared', True, True), )),
-                (dict(), dict(k1='v1'), dict(k2='v2', k3='v3'))):
-
-            callargs = dict()
-            for p in params:
-                callargs[p[0]] = p[2]
-            callargs.update(kwargs)
-
-            self.assertEqual(self.client.networks_post(**callargs), 'ret val')
-            self._assert(
-                post, '/networks', set_param,
-                params=params, data=None, **kwargs)
-
-            json_data = dict(id='some id', other_param='other val')
-            callargs['json_data'] = json_data
-            self.assertEqual(self.client.networks_post(**callargs), 'ret val')
-            self._assert(
-                post, '/networks', set_param, params,
-                data=dumps(json_data), **kwargs)
-
-    @patch('kamaki.clients.Client.set_param')
-    @patch('kamaki.clients.Client.put', return_value='ret val')
-    def test_networks_put(self, put, set_param):
-        netid = 'netid'
-        for params, kwargs in product(
-                [p for p in product(
-                    (
-                        ('admin_state_up', False, None),
-                        ('admin_state_up', True, True)),
-                    (('shared', False, None), ('shared', True, True)),
-                )],
-                (dict(), dict(k1='v1'), dict(k2='v2', k3='v3'))):
-
-            callargs = dict()
-            for p in params:
-                callargs[p[0]] = p[2]
-            callargs.update(kwargs)
-
-            self.assertEqual(
-                self.client.networks_put(netid, **callargs), 'ret val')
-            self._assert(
-                put, '/networks/%s' % netid, set_param, params,
-                data=None, **kwargs)
-
-            json_data = dict(id='some id', other_param='other val')
-            callargs['json_data'] = json_data
-            self.assertEqual(
-                self.client.networks_put(netid, **callargs), 'ret val')
-            self._assert(
-                put, '/networks/%s' % netid, set_param, params,
-                data=dumps(json_data), **kwargs)
-
-    @patch('kamaki.clients.Client.delete', return_value='ret val')
-    def test_networks_delete(self, delete):
-        netid = 'netid'
-        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
-            self.assertEqual(
-                self.client.networks_delete(netid, **kwargs), 'ret val')
-            self._assert(delete, '/networks/%s' % netid, **kwargs)
-
-    @patch('kamaki.clients.Client.get', return_value='ret val')
-    def test_subnets_get(self, get):
-        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
-            self.assertEqual(self.client.subnets_get(**kwargs), 'ret val')
-            self._assert(get, '/subnets', **kwargs)
-
-            subnet_id = 'subnet id'
-            self.assertEqual(
-                self.client.subnets_get(subnet_id=subnet_id, **kwargs),
-                'ret val')
-            self._assert(get, '/subnets/%s' % subnet_id, **kwargs)
-
-    @patch('kamaki.clients.Client.post', return_value='ret val')
-    def test_subnets_post(self, post):
-        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
-            self.assertEqual(self.client.subnets_post(**kwargs), 'ret val')
-            self._assert(post, '/subnets', **kwargs)
-
-    @patch('kamaki.clients.Client.put', return_value='ret val')
-    def test_subnets_put(self, put):
-        subnet_id = 'subid'
-        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
-            self.assertEqual(
-                self.client.subnets_put(subnet_id, **kwargs), 'ret val')
-            self._assert(put, '/subnets/%s' % subnet_id, **kwargs)
-
-    @patch('kamaki.clients.Client.delete', return_value='ret val')
-    def test_subnets_delete(self, delete):
-        netid = 'netid'
-        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
-            self.assertEqual(
-                self.client.subnets_delete(netid, **kwargs), 'ret val')
-            self._assert(delete, '/subnets/%s' % netid, **kwargs)
-
-    @patch('kamaki.clients.Client.get', return_value='ret val')
-    def test_ports_get(self, get):
-        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
-            self.assertEqual(self.client.ports_get(**kwargs), 'ret val')
-            self._assert(get, '/ports', **kwargs)
-
-            port_id = 'port id'
-            self.assertEqual(
-                self.client.ports_get(port_id=port_id, **kwargs),
-                'ret val')
-            self._assert(get, '/ports/%s' % port_id, **kwargs)
-
-    @patch('kamaki.clients.Client.set_param')
-    @patch('kamaki.clients.Client.post', return_value='ret val')
-    def test_ports_post(self, post, set_param):
-        for params, kwargs in product(
-                [p for p in product(
-                    (
-                        ('name', 'port name', 'port name'),
-                        ('name', None, None)),
-                    (
-                        ('mac_address', 'max address', 'max address'),
-                        ('mac_address', None, None)),
-                    (
-                        ('fixed_ips', 'fixed ip', 'fixed ip'),
-                        ('fixed_ips', None, None)),
-                    (
-                        ('security_groups', 'sec groups', 'sec groups'),
-                        ('security_groups', None, None))
-                )],
-                (dict(), dict(k1='v1'), dict(k2='v2', k3='v3'))):
-
-            callargs = dict()
-            for p in params:
-                callargs[p[0]] = p[2]
-            callargs.update(kwargs)
-
-            self.assertEqual(self.client.ports_post(**callargs), 'ret val')
-            self._assert(
-                post, '/ports', set_param,
-                params=params, data=None, **kwargs)
-
-            json_data = dict(id='some id', other_param='other val')
-            callargs['json_data'] = json_data
-            self.assertEqual(self.client.ports_post(**callargs), 'ret val')
-            self._assert(
-                post, '/ports', set_param, params,
-                data=dumps(json_data), **kwargs)
-
-    @patch('kamaki.clients.Client.set_param')
-    @patch('kamaki.clients.Client.put', return_value='ret val')
-    def test_ports_put(self, put, set_param):
-        port_id = 'portid'
-        for params, kwargs in product(
-                [p for p in product(
-                    (
-                        ('name', 'port name', 'port name'),
-                        ('name', None, None)),
-                    (
-                        ('mac_address', 'max address', 'max address'),
-                        ('mac_address', None, None)),
-                    (
-                        ('fixed_ips', 'fixed ip', 'fixed ip'),
-                        ('fixed_ips', None, None)),
-                    (
-                        ('security_groups', 'sec groups', 'sec groups'),
-                        ('security_groups', None, None))
-                )],
-                (dict(), dict(k1='v1'), dict(k2='v2', k3='v3'))):
-
-            callargs = dict()
-            for p in params:
-                callargs[p[0]] = p[2]
-            callargs.update(kwargs)
-
-            self.assertEqual(
-                self.client.ports_put(port_id, **callargs), 'ret val')
-            self._assert(
-                put, '/ports/%s' % port_id, set_param,
-                params=params, data=None, **kwargs)
-
-            json_data = dict(id='some id', other_param='other val')
-            callargs['json_data'] = json_data
-            self.assertEqual(
-                self.client.ports_put(port_id, **callargs), 'ret val')
-            self._assert(
-                put, '/ports/%s' % port_id, set_param, params,
-                data=dumps(json_data), **kwargs)
-
-
-class FakeObject(object):
-
-    json = None
-
-
-class NetworkClient(TestCase):
-
-    """Set up a ComputesRest thorough test"""
-    def setUp(self):
-        self.url = 'http://network.example.com'
-        self.token = 'n2tw0rk70k3n'
-        self.client = network.NetworkClient(self.url, self.token)
-
-    def tearDown(self):
-        del self.client
-
-    @patch(
-        'kamaki.clients.network.NetworkClient.networks_get',
-        return_value=FakeObject())
-    def test_list_networks(self, networks_get):
-        FakeObject.json = dict(networks='ret val')
-        self.assertEqual(self.client.list_networks(), 'ret val')
-        networks_get.assert_called_once_with(success=200)
-
-    @patch(
-        'kamaki.clients.network.NetworkClient.networks_post',
-        return_value=FakeObject())
-    def test_create_network(self, networks_post):
-        FakeObject.json = dict(network='ret val')
-        req = dict()
-        for kwargs in (dict(shared=None), dict(shared=True)):
-            for body_params in product(
-                    (('name', None, ''), ('name', 'some name', 'some name')),
-                    (
-                        ('admin_state_up', None, False),
-                        ('admin_state_up', True, True))):
-                fullargs = dict(kwargs)
-                for k, v, exp in body_params:
-                    fullargs[k] = v
-                    req[k] = exp
-                self.assertEqual(
-                    self.client.create_network(**fullargs), 'ret val')
-                expargs = dict(kwargs)
-                expargs = dict(json_data=dict(network=req), success=201)
-                expargs.update(kwargs)
-                self.assertEqual(networks_post.mock_calls[-1], call(**expargs))
-
-
-if __name__ == '__main__':
-    from sys import argv
-    from kamaki.clients.test import runTestCase
-    not_found = True
-    if not argv[1:] or argv[1] == 'NetworkClient':
-        not_found = False
-        runTestCase(NetworkClient, 'Network Client', argv[2:])
-    if not argv[1:] or argv[1] == 'NetworkRest':
-        not_found = False
-        runTestCase(NetworkRestClient, 'NetworkRest Client', argv[2:])
-    if not_found:
-        print('TestCase %s not found' % argv[1])
diff --git a/kamaki/clients/networking/__init__.py b/kamaki/clients/networking/__init__.py
new file mode 100644
index 0000000..6c39d0e
--- /dev/null
+++ b/kamaki/clients/networking/__init__.py
@@ -0,0 +1,49 @@
+# Copyright 2013 GRNET S.A. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+#   1. Redistributions of source code must retain the above
+#      copyright notice, this list of conditions and the following
+#      disclaimer.
+#
+#   2. Redistributions in binary form must reproduce the above
+#      copyright notice, this list of conditions and the following
+#      disclaimer in the documentation and/or other materials
+#      provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# The views and conclusions contained in the software and
+# documentation are those of the authors and should not be
+# interpreted as representing official policies, either expressed
+# or implied, of GRNET S.A.
+
+from kamaki.clients import ClientError
+from kamaki.clients.networking.rest_api import NetworkingRestClient
+
+
+class NetworkingClient(NetworkingRestClient):
+    """OpenStack Network API 2.0 client"""
+
+    def list_networks(self):
+        r = self.networks_get(success=200)
+        return r.json['networks']
+
+    def create_network(self, name=None, admin_state_up=None, shared=None):
+        req = dict(network=dict(
+            name=name or '', admin_state_up=bool(admin_state_up)))
+        r = self.networks_post(json_data=req, shared=shared, success=201)
+        return r.json['network']
diff --git a/kamaki/clients/networking/rest_api.py b/kamaki/clients/networking/rest_api.py
new file mode 100644
index 0000000..821d5eb
--- /dev/null
+++ b/kamaki/clients/networking/rest_api.py
@@ -0,0 +1,111 @@
+# Copyright 2013 GRNET S.A. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+#   1. Redistributions of source code must retain the above
+#      copyright notice, this list of conditions and the following
+#      disclaimer.
+#
+#   2. Redistributions in binary form must reproduce the above
+#      copyright notice, this list of conditions and the following
+#      disclaimer in the documentation and/or other materials
+#      provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# The views and conclusions contained in the software and
+# documentation are those of the authors and should not be
+# interpreted as representing official policies, either expressed
+# or implied, of GRNET S.A.
+
+from kamaki.clients import Client
+from kamaki.clients.utils import path4url
+from json import dumps
+
+
+class NetworkingRestClient(Client):
+
+    def networks_get(self, network_id=None, **kwargs):
+        if network_id:
+            return self.get(path4url('networks', network_id), **kwargs)
+        return self.get(path4url('networks'), **kwargs)
+
+    def networks_post(self, json_data=None, shared=None, **kwargs):
+        path = path4url('networks')
+        self.set_param('shared', bool(shared), iff=shared)
+        return self.post(
+            path, data=dumps(json_data) if json_data else None, **kwargs)
+
+    def networks_put(
+            self, network_id,
+            json_data=None, admin_state_up=None, shared=None, **kwargs):
+        path = path4url('networks', network_id)
+
+        self.set_param(
+            'admin_state_up', bool(admin_state_up), iff=admin_state_up)
+        self.set_param('shared', bool(shared), iff=shared)
+
+        return self.put(
+            path, data=dumps(json_data) if json_data else None, **kwargs)
+
+    def networks_delete(self, network_id, **kwargs):
+        return self.delete(path4url('networks', network_id), **kwargs)
+
+    def subnets_get(self, subnet_id=None, **kwargs):
+        if subnet_id:
+            return self.get(path4url('subnets', subnet_id), **kwargs)
+        return self.get(path4url('subnets'), **kwargs)
+
+    def subnets_post(self, **kwargs):
+        return self.post(path4url('subnets'), **kwargs)
+
+    def subnets_put(self, subnet_id, **kwargs):
+        return self.put(path4url('subnets', subnet_id), **kwargs)
+
+    def subnets_delete(self, subnet_id, **kwargs):
+        return self.delete(path4url('subnets', subnet_id), **kwargs)
+
+    def ports_get(self, port_id=None, **kwargs):
+        if port_id:
+            return self.get(path4url('ports', port_id), **kwargs)
+        return self.get(path4url('ports'), **kwargs)
+
+    def ports_post(
+            self,
+            json_data=None,
+            name=None, mac_address=None, fixed_ips=None, security_groups=None,
+            **kwargs):
+        self.set_param('name', name, iff=name)
+        self.set_param('mac_address', mac_address, iff=mac_address)
+        self.set_param('fixed_ips', fixed_ips, iff=fixed_ips)
+        self.set_param('security_groups', security_groups, iff=security_groups)
+        data = dumps(json_data) if json_data else None
+        return self.post(path4url('ports'), data=data, **kwargs)
+
+    def ports_put(
+            self, port_id,
+            json_data=None,
+            name=None, mac_address=None, fixed_ips=None, security_groups=None,
+            **kwargs):
+        self.set_param('name', name, iff=name)
+        self.set_param('mac_address', mac_address, iff=mac_address)
+        self.set_param('fixed_ips', fixed_ips, iff=fixed_ips)
+        self.set_param('security_groups', security_groups, iff=security_groups)
+        data = dumps(json_data) if json_data else None
+        return self.put(path4url('ports', port_id), data=data, **kwargs)
+
+    def ports_delete(self, port_id, **kwargs):
+        return self.delete(path4url('ports', port_id), **kwargs)
diff --git a/kamaki/clients/networking/test.py b/kamaki/clients/networking/test.py
new file mode 100644
index 0000000..21b6725
--- /dev/null
+++ b/kamaki/clients/networking/test.py
@@ -0,0 +1,322 @@
+# Copyright 2013 GRNET S.A. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+#   1. Redistributions of source code must retain the above
+#      copyright notice, this list of conditions and the following
+#      disclaimer.
+#
+#   2. Redistributions in binary form must reproduce the above
+#      copyright notice, this list of conditions and the following
+#      disclaimer in the documentation and/or other materials
+#      provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# The views and conclusions contained in the software and
+# documentation are those of the authors and should not be
+# interpreted as representing official policies, either expressed
+# or implied, of GRNET S.A.
+
+from mock import patch, call
+from unittest import TestCase
+from itertools import product
+from json import dumps
+
+from kamaki.clients import networking
+
+
+class NetworkingRestClient(TestCase):
+
+    """Set up a ComputesRest thorough test"""
+    def setUp(self):
+        self.url = 'http://networking.example.com'
+        self.token = 'n2tw0rk70k3n'
+        self.client = networking.NetworkingRestClient(self.url, self.token)
+
+    def tearDown(self):
+        del self.client
+
+    def _assert(self, method_call, path, set_param=None, params=(), **kwargs):
+        """Assert the REST method call is called as expected"""
+        x0 = - len(params)
+        for i, (k, v, c) in enumerate(params):
+            self.assertEqual(set_param.mock_calls[x0 + i], call(k, v, iff=c))
+
+        self.assertEqual(method_call.mock_calls[-1], call(path, **kwargs))
+
+    @patch('kamaki.clients.Client.get', return_value='ret val')
+    def test_networks_get(self, get):
+        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
+            self.assertEqual(self.client.networks_get(**kwargs), 'ret val')
+            self._assert(get, '/networks', **kwargs)
+
+            netid = 'netid'
+            self.assertEqual(
+                self.client.networks_get(network_id=netid, **kwargs),
+                'ret val')
+            self._assert(get, '/networks/%s' % netid, **kwargs)
+
+    @patch('kamaki.clients.Client.set_param')
+    @patch('kamaki.clients.Client.post', return_value='ret val')
+    def test_networks_post(self, post, set_param):
+        for params, kwargs in product(
+                (
+                    (('shared', False, None), ),
+                    (('shared', True, True), )),
+                (dict(), dict(k1='v1'), dict(k2='v2', k3='v3'))):
+
+            callargs = dict()
+            for p in params:
+                callargs[p[0]] = p[2]
+            callargs.update(kwargs)
+
+            self.assertEqual(self.client.networks_post(**callargs), 'ret val')
+            self._assert(
+                post, '/networks', set_param,
+                params=params, data=None, **kwargs)
+
+            json_data = dict(id='some id', other_param='other val')
+            callargs['json_data'] = json_data
+            self.assertEqual(self.client.networks_post(**callargs), 'ret val')
+            self._assert(
+                post, '/networks', set_param, params,
+                data=dumps(json_data), **kwargs)
+
+    @patch('kamaki.clients.Client.set_param')
+    @patch('kamaki.clients.Client.put', return_value='ret val')
+    def test_networks_put(self, put, set_param):
+        netid = 'netid'
+        for params, kwargs in product(
+                [p for p in product(
+                    (
+                        ('admin_state_up', False, None),
+                        ('admin_state_up', True, True)),
+                    (('shared', False, None), ('shared', True, True)),
+                )],
+                (dict(), dict(k1='v1'), dict(k2='v2', k3='v3'))):
+
+            callargs = dict()
+            for p in params:
+                callargs[p[0]] = p[2]
+            callargs.update(kwargs)
+
+            self.assertEqual(
+                self.client.networks_put(netid, **callargs), 'ret val')
+            self._assert(
+                put, '/networks/%s' % netid, set_param, params,
+                data=None, **kwargs)
+
+            json_data = dict(id='some id', other_param='other val')
+            callargs['json_data'] = json_data
+            self.assertEqual(
+                self.client.networks_put(netid, **callargs), 'ret val')
+            self._assert(
+                put, '/networks/%s' % netid, set_param, params,
+                data=dumps(json_data), **kwargs)
+
+    @patch('kamaki.clients.Client.delete', return_value='ret val')
+    def test_networks_delete(self, delete):
+        netid = 'netid'
+        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
+            self.assertEqual(
+                self.client.networks_delete(netid, **kwargs), 'ret val')
+            self._assert(delete, '/networks/%s' % netid, **kwargs)
+
+    @patch('kamaki.clients.Client.get', return_value='ret val')
+    def test_subnets_get(self, get):
+        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
+            self.assertEqual(self.client.subnets_get(**kwargs), 'ret val')
+            self._assert(get, '/subnets', **kwargs)
+
+            subnet_id = 'subnet id'
+            self.assertEqual(
+                self.client.subnets_get(subnet_id=subnet_id, **kwargs),
+                'ret val')
+            self._assert(get, '/subnets/%s' % subnet_id, **kwargs)
+
+    @patch('kamaki.clients.Client.post', return_value='ret val')
+    def test_subnets_post(self, post):
+        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
+            self.assertEqual(self.client.subnets_post(**kwargs), 'ret val')
+            self._assert(post, '/subnets', **kwargs)
+
+    @patch('kamaki.clients.Client.put', return_value='ret val')
+    def test_subnets_put(self, put):
+        subnet_id = 'subid'
+        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
+            self.assertEqual(
+                self.client.subnets_put(subnet_id, **kwargs), 'ret val')
+            self._assert(put, '/subnets/%s' % subnet_id, **kwargs)
+
+    @patch('kamaki.clients.Client.delete', return_value='ret val')
+    def test_subnets_delete(self, delete):
+        netid = 'netid'
+        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
+            self.assertEqual(
+                self.client.subnets_delete(netid, **kwargs), 'ret val')
+            self._assert(delete, '/subnets/%s' % netid, **kwargs)
+
+    @patch('kamaki.clients.Client.get', return_value='ret val')
+    def test_ports_get(self, get):
+        for kwargs in (dict(), dict(k1='v1'), dict(k2='v2', k3='v3')):
+            self.assertEqual(self.client.ports_get(**kwargs), 'ret val')
+            self._assert(get, '/ports', **kwargs)
+
+            port_id = 'port id'
+            self.assertEqual(
+                self.client.ports_get(port_id=port_id, **kwargs),
+                'ret val')
+            self._assert(get, '/ports/%s' % port_id, **kwargs)
+
+    @patch('kamaki.clients.Client.set_param')
+    @patch('kamaki.clients.Client.post', return_value='ret val')
+    def test_ports_post(self, post, set_param):
+        for params, kwargs in product(
+                [p for p in product(
+                    (
+                        ('name', 'port name', 'port name'),
+                        ('name', None, None)),
+                    (
+                        ('mac_address', 'max address', 'max address'),
+                        ('mac_address', None, None)),
+                    (
+                        ('fixed_ips', 'fixed ip', 'fixed ip'),
+                        ('fixed_ips', None, None)),
+                    (
+                        ('security_groups', 'sec groups', 'sec groups'),
+                        ('security_groups', None, None))
+                )],
+                (dict(), dict(k1='v1'), dict(k2='v2', k3='v3'))):
+
+            callargs = dict()
+            for p in params:
+                callargs[p[0]] = p[2]
+            callargs.update(kwargs)
+
+            self.assertEqual(self.client.ports_post(**callargs), 'ret val')
+            self._assert(
+                post, '/ports', set_param,
+                params=params, data=None, **kwargs)
+
+            json_data = dict(id='some id', other_param='other val')
+            callargs['json_data'] = json_data
+            self.assertEqual(self.client.ports_post(**callargs), 'ret val')
+            self._assert(
+                post, '/ports', set_param, params,
+                data=dumps(json_data), **kwargs)
+
+    @patch('kamaki.clients.Client.set_param')
+    @patch('kamaki.clients.Client.put', return_value='ret val')
+    def test_ports_put(self, put, set_param):
+        port_id = 'portid'
+        for params, kwargs in product(
+                [p for p in product(
+                    (
+                        ('name', 'port name', 'port name'),
+                        ('name', None, None)),
+                    (
+                        ('mac_address', 'max address', 'max address'),
+                        ('mac_address', None, None)),
+                    (
+                        ('fixed_ips', 'fixed ip', 'fixed ip'),
+                        ('fixed_ips', None, None)),
+                    (
+                        ('security_groups', 'sec groups', 'sec groups'),
+                        ('security_groups', None, None))
+                )],
+                (dict(), dict(k1='v1'), dict(k2='v2', k3='v3'))):
+
+            callargs = dict()
+            for p in params:
+                callargs[p[0]] = p[2]
+            callargs.update(kwargs)
+
+            self.assertEqual(
+                self.client.ports_put(port_id, **callargs), 'ret val')
+            self._assert(
+                put, '/ports/%s' % port_id, set_param,
+                params=params, data=None, **kwargs)
+
+            json_data = dict(id='some id', other_param='other val')
+            callargs['json_data'] = json_data
+            self.assertEqual(
+                self.client.ports_put(port_id, **callargs), 'ret val')
+            self._assert(
+                put, '/ports/%s' % port_id, set_param, params,
+                data=dumps(json_data), **kwargs)
+
+
+class FakeObject(object):
+
+    json = None
+
+
+class NetworkingClient(TestCase):
+
+    """Set up a ComputesRest thorough test"""
+    def setUp(self):
+        self.url = 'http://network.example.com'
+        self.token = 'n2tw0rk70k3n'
+        self.client = networking.NetworkingClient(self.url, self.token)
+
+    def tearDown(self):
+        del self.client
+
+    @patch(
+        'kamaki.clients.networking.NetworkingClient.networks_get',
+        return_value=FakeObject())
+    def test_list_networks(self, networks_get):
+        FakeObject.json = dict(networks='ret val')
+        self.assertEqual(self.client.list_networks(), 'ret val')
+        networks_get.assert_called_once_with(success=200)
+
+    @patch(
+        'kamaki.clients.networking.NetworkingClient.networks_post',
+        return_value=FakeObject())
+    def test_create_network(self, networks_post):
+        FakeObject.json = dict(network='ret val')
+        req = dict()
+        for kwargs in (dict(shared=None), dict(shared=True)):
+            for body_params in product(
+                    (('name', None, ''), ('name', 'some name', 'some name')),
+                    (
+                        ('admin_state_up', None, False),
+                        ('admin_state_up', True, True))):
+                fullargs = dict(kwargs)
+                for k, v, exp in body_params:
+                    fullargs[k] = v
+                    req[k] = exp
+                self.assertEqual(
+                    self.client.create_network(**fullargs), 'ret val')
+                expargs = dict(kwargs)
+                expargs = dict(json_data=dict(network=req), success=201)
+                expargs.update(kwargs)
+                self.assertEqual(networks_post.mock_calls[-1], call(**expargs))
+
+
+if __name__ == '__main__':
+    from sys import argv
+    from kamaki.clients.test import runTestCase
+    not_found = True
+    if not argv[1:] or argv[1] == 'NetworkingClient':
+        not_found = False
+        runTestCase(NetworkingClient, 'Networking Client', argv[2:])
+    if not argv[1:] or argv[1] == 'NetworkingRest':
+        not_found = False
+        runTestCase(NetworkingRestClient, 'NetworkingRest Client', argv[2:])
+    if not_found:
+        print('TestCase %s not found' % argv[1])
diff --git a/kamaki/clients/test.py b/kamaki/clients/test.py
index 0ad4236..13d8e21 100644
--- a/kamaki/clients/test.py
+++ b/kamaki/clients/test.py
@@ -41,7 +41,8 @@ from random import randint
 from kamaki.clients.utils.test import Utils
 from kamaki.clients.astakos.test import AstakosClient
 from kamaki.clients.compute.test import ComputeClient, ComputeRestClient
-from kamaki.clients.network.test import NetworkClient, NetworkRestClient
+from kamaki.clients.networking.test import (
+    NetworkingClient, NetworkingRestClient)
 from kamaki.clients.cyclades.test import CycladesClient
 from kamaki.clients.cyclades.test import CycladesRestClient
 from kamaki.clients.image.test import ImageClient
diff --git a/setup.py b/setup.py
index 6398889..e9f9292 100755
--- a/setup.py
+++ b/setup.py
@@ -76,6 +76,7 @@ setup(
         'kamaki.clients.astakos',
         'kamaki.clients.compute',
         'kamaki.clients.cyclades',
+        'kamaki.clients.networking'
     ],
     classifiers=[
         'Operating System :: OS Independent',
