commit 94537e349e6ae82dfe123ffa13e46a3c7f3056cf
Author: Christos Stavrakakis <cstavr@grnet.gr>
Date:   Thu Jul 11 15:51:41 2013 +0300

    cyclades: Move tests in tests directory

diff --git a/snf-cyclades-app/synnefo/api/test/__init__.py b/snf-cyclades-app/synnefo/api/test/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/snf-cyclades-app/synnefo/api/test/extensions.py b/snf-cyclades-app/synnefo/api/test/extensions.py
deleted file mode 100644
index 180ea57..0000000
--- a/snf-cyclades-app/synnefo/api/test/extensions.py
+++ /dev/null
@@ -1,59 +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.
-
-import json
-
-from snf_django.utils.testing import BaseAPITest
-from synnefo.lib.services import get_service_path
-from synnefo.cyclades_settings import cyclades_services
-from synnefo.lib import join_urls
-
-COMPUTE_URL = get_service_path(cyclades_services, 'compute',
-                               version='v2.0')
-EXTENSIONS_URL = join_urls(COMPUTE_URL, "extensions/")
-
-
-class ExtensionsAPITest(BaseAPITest):
-    def test_list(self):
-        response = self.get(EXTENSIONS_URL, "user")
-        self.assertSuccess(response)
-        extensions = json.loads(response.content)["extensions"]
-        self.assertEqual(extensions, [])
-
-    def test_get(self):
-        response = self.get(join_urls(EXTENSIONS_URL, "SNF"), "user")
-        self.assertEqual(response.status_code, 404)
-        response = self.get(join_urls(EXTENSIONS_URL, "SNF_asfas_da"), "user")
-        self.assertEqual(response.status_code, 404)
-        response = self.get(join_urls(EXTENSIONS_URL, "SNF-AD"), "user")
-        self.assertEqual(response.status_code, 404)
diff --git a/snf-cyclades-app/synnefo/api/test/flavors.py b/snf-cyclades-app/synnefo/api/test/flavors.py
deleted file mode 100644
index bc97987..0000000
--- a/snf-cyclades-app/synnefo/api/test/flavors.py
+++ /dev/null
@@ -1,146 +0,0 @@
-# Copyright 2012 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.
-
-import json
-
-from snf_django.utils.testing import BaseAPITest
-from synnefo.db.models import Flavor
-from synnefo.db.models_factory import FlavorFactory
-from synnefo.lib.services import get_service_path
-from synnefo.cyclades_settings import cyclades_services
-from synnefo.lib import join_urls
-
-
-class FlavorAPITest(BaseAPITest):
-
-    def setUp(self):
-        self.flavor1 = FlavorFactory()
-        self.flavor2 = FlavorFactory(deleted=True)
-        self.flavor3 = FlavorFactory()
-        self.compute_path = get_service_path(cyclades_services, 'compute',
-                                             version='v2.0')
-
-
-    def myget(self, path):
-        path = join_urls(self.compute_path, path)
-        return self.get(path)
-
-
-    def test_flavor_list(self):
-        """Test if the expected list of flavors is returned."""
-        response = self.myget('flavors')
-        self.assertSuccess(response)
-
-        api_flavors = json.loads(response.content)['flavors']
-        db_flavors = Flavor.objects.filter(deleted=False)
-        self.assertEqual(len(api_flavors), len(db_flavors))
-        for api_flavor in api_flavors:
-            db_flavor = Flavor.objects.get(id=api_flavor['id'])
-            self.assertEqual(api_flavor['id'], db_flavor.id)
-            self.assertEqual(api_flavor['name'], db_flavor.name)
-
-    def test_flavors_details(self):
-        """Test if the flavors details are returned."""
-        response = self.myget('flavors/detail')
-        self.assertSuccess(response)
-
-        db_flavors = Flavor.objects.filter(deleted=False)
-        api_flavors = json.loads(response.content)['flavors']
-
-        self.assertEqual(len(db_flavors), len(api_flavors))
-
-        for i in range(0, len(db_flavors)):
-            api_flavor = api_flavors[i]
-            db_flavor = Flavor.objects.get(id=db_flavors[i].id)
-            self.assertEqual(api_flavor['vcpus'], db_flavor.cpu)
-            self.assertEqual(api_flavor['id'], db_flavor.id)
-            self.assertEqual(api_flavor['disk'], db_flavor.disk)
-            self.assertEqual(api_flavor['name'], db_flavor.name)
-            self.assertEqual(api_flavor['ram'], db_flavor.ram)
-            self.assertEqual(api_flavor['SNF:disk_template'],
-                                        db_flavor.disk_template)
-
-    def test_flavor_details(self):
-        """Test if the expected flavor is returned."""
-        flavor = self.flavor3
-
-        response = self.myget('flavors/%d' % flavor.id)
-        self.assertSuccess(response)
-
-        api_flavor = json.loads(response.content)['flavor']
-        db_flavor = Flavor.objects.get(id=flavor.id)
-        self.assertEqual(api_flavor['vcpus'], db_flavor.cpu)
-        self.assertEqual(api_flavor['id'], db_flavor.id)
-        self.assertEqual(api_flavor['disk'], db_flavor.disk)
-        self.assertEqual(api_flavor['name'], db_flavor.name)
-        self.assertEqual(api_flavor['ram'], db_flavor.ram)
-        self.assertEqual(api_flavor['SNF:disk_template'],
-                         db_flavor.disk_template)
-
-    def test_deleted_flavor_details(self):
-        """Test that API returns details for deleted flavors"""
-        flavor = self.flavor2
-        response = self.myget('flavors/%d' % flavor.id)
-        self.assertSuccess(response)
-        api_flavor = json.loads(response.content)['flavor']
-        self.assertEquals(api_flavor['name'], flavor.name)
-
-    def test_deleted_flavors_list(self):
-        """Test that deleted flavors do not appear to flavors list"""
-        response = self.myget('flavors')
-        self.assertSuccess(response)
-        api_flavors = json.loads(response.content)['flavors']
-        self.assertEqual(len(api_flavors), 2)
-
-    def test_deleted_flavors_details(self):
-        """Test that deleted flavors do not appear to flavors detail list"""
-        FlavorFactory(deleted=True)
-        response = self.myget('flavors/detail')
-        self.assertSuccess(response)
-        api_flavors = json.loads(response.content)['flavors']
-        self.assertEqual(len(api_flavors), 2)
-
-    def test_wrong_flavor(self):
-        """Test 404 result when requesting a flavor that does not exist."""
-
-        # XXX: flavors/22 below fails for no apparent reason
-        response = self.myget('flavors/%d' % 23)
-        self.assertItemNotFound(response)
-
-    def test_catch_wrong_api_paths(self, *args):
-        response = self.myget('nonexistent')
-        self.assertEqual(response.status_code, 400)
-        try:
-            error = json.loads(response.content)
-        except ValueError:
-            self.assertTrue(False)
diff --git a/snf-cyclades-app/synnefo/api/test/floating_ips.py b/snf-cyclades-app/synnefo/api/test/floating_ips.py
deleted file mode 100644
index 8f6880f..0000000
--- a/snf-cyclades-app/synnefo/api/test/floating_ips.py
+++ /dev/null
@@ -1,334 +0,0 @@
-# Copyright 2012 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.
-
-import json
-
-from snf_django.utils.testing import BaseAPITest, mocked_quotaholder
-from synnefo.db.models import FloatingIP
-from synnefo.db.models_factory import (FloatingIPFactory, NetworkFactory,
-                                       VirtualMachineFactory,
-                                       NetworkInterfaceFactory,
-                                       BackendNetworkFactory)
-from mock import patch, Mock
-from functools import partial
-
-from synnefo.cyclades_settings import cyclades_services
-from synnefo.lib.services import get_service_path
-from synnefo.lib import join_urls
-
-
-compute_path = get_service_path(cyclades_services, "compute", version="v2.0")
-URL = join_urls(compute_path, "os-floating-ips")
-NETWORKS_URL = join_urls(compute_path, "networks")
-SERVERS_URL = join_urls(compute_path, "servers")
-
-FloatingIPPoolFactory = partial(NetworkFactory, public=True, deleted=False,
-                                floating_ip_pool=True)
-
-
-class FloatingIPAPITest(BaseAPITest):
-    def test_no_floating_ip(self):
-        response = self.get(URL)
-        self.assertSuccess(response)
-        self.assertEqual(json.loads(response.content)["floating_ips"], [])
-
-    def test_list_ips(self):
-        ip = FloatingIPFactory(userid="user1")
-        FloatingIPFactory(userid="user1", deleted=True)
-        with mocked_quotaholder():
-            response = self.get(URL, "user1")
-        self.assertSuccess(response)
-        api_ip = json.loads(response.content)["floating_ips"][0]
-        self.assertEqual(api_ip,
-                         {"instance_id": str(ip.machine.id), "ip": ip.ipv4,
-                          "fixed_ip": None, "id": str(ip.id),  "pool":
-                          str(ip.network.id)})
-
-    def test_get_ip(self):
-        ip = FloatingIPFactory(userid="user1")
-        with mocked_quotaholder():
-            response = self.get(URL + "/%s" % ip.id, "user1")
-        self.assertSuccess(response)
-        api_ip = json.loads(response.content)["floating_ip"]
-        self.assertEqual(api_ip,
-                         {"instance_id": str(ip.machine.id), "ip": ip.ipv4,
-                          "fixed_ip": None, "id": str(ip.id),  "pool":
-                          str(ip.network.id)})
-
-    def test_wrong_user(self):
-        ip = FloatingIPFactory(userid="user1")
-        with mocked_quotaholder():
-            response = self.delete(URL + "/%s" % ip.id, "user2")
-        self.assertItemNotFound(response)
-
-    def test_deleted_ip(self):
-        ip = FloatingIPFactory(userid="user1", deleted=True)
-        with mocked_quotaholder():
-            response = self.delete(URL + "/%s" % ip.id, "user1")
-        self.assertItemNotFound(response)
-
-    def test_reserve(self):
-        net = FloatingIPPoolFactory(userid="test_user",
-                                    subnet="192.168.2.0/24",
-                                    gateway=None)
-        request = {'pool': net.id}
-        with mocked_quotaholder():
-            response = self.post(URL, "test_user", json.dumps(request), "json")
-        self.assertSuccess(response)
-        ip = FloatingIP.objects.get()
-        self.assertEqual(ip.ipv4, "192.168.2.1")
-        self.assertEqual(ip.machine, None)
-        self.assertEqual(ip.network, net)
-        self.assertEqual(json.loads(response.content)["floating_ip"],
-                         {"instance_id": None, "ip": "192.168.2.1",
-                          "fixed_ip": None, "id": "1", "pool": "1"})
-
-    def test_reserve_no_pool(self):
-        # No networks
-        with mocked_quotaholder():
-            response = self.post(URL, "test_user", json.dumps({}), "json")
-        self.assertFault(response, 413, "overLimit")
-        # Full network
-        FloatingIPPoolFactory(userid="test_user",
-                              subnet="192.168.2.0/32",
-                              gateway=None)
-        with mocked_quotaholder():
-            response = self.post(URL, "test_user", json.dumps({}), "json")
-        self.assertFault(response, 413, "overLimit")
-        # Success
-        net2 = FloatingIPPoolFactory(userid="test_user",
-                                     subnet="192.168.2.0/24",
-                                     gateway=None)
-        with mocked_quotaholder():
-            response = self.post(URL, "test_user", json.dumps({}), "json")
-        self.assertSuccess(response)
-        self.assertEqual(json.loads(response.content)["floating_ip"],
-                         {"instance_id": None, "ip": "192.168.2.1",
-                          "fixed_ip": None, "id": "1", "pool": str(net2.id)})
-
-    def test_reserve_full(self):
-        net = FloatingIPPoolFactory(userid="test_user",
-                                    subnet="192.168.2.0/32")
-        request = {'pool': net.id}
-        with mocked_quotaholder():
-            response = self.post(URL, "test_user", json.dumps(request), "json")
-        self.assertEqual(response.status_code, 413)
-
-    def test_reserve_with_address(self):
-        net = FloatingIPPoolFactory(userid="test_user",
-                                    subnet="192.168.2.0/24")
-        request = {'pool': net.id, "address": "192.168.2.10"}
-        with mocked_quotaholder():
-            response = self.post(URL, "test_user", json.dumps(request), "json")
-        self.assertSuccess(response)
-        self.assertEqual(json.loads(response.content)["floating_ip"],
-                         {"instance_id": None, "ip": "192.168.2.10",
-                          "fixed_ip": None, "id": "1", "pool": "1"})
-
-        # Already reserved
-        FloatingIPFactory(network=net, ipv4="192.168.2.3")
-        request = {'pool': net.id, "address": "192.168.2.3"}
-        with mocked_quotaholder():
-            response = self.post(URL, "test_user", json.dumps(request), "json")
-        self.assertFault(response, 409, "conflict")
-
-        # Already used
-        pool = net.get_pool()
-        pool.reserve("192.168.2.5")
-        pool.save()
-        # ..by another_user
-        nic = NetworkInterfaceFactory(network=net, ipv4="192.168.2.5",
-                                      machine__userid="test2")
-        request = {'pool': net.id, "address": "192.168.2.5"}
-        with mocked_quotaholder():
-            response = self.post(URL, "test_user", json.dumps(request), "json")
-        self.assertFault(response, 409, "conflict")
-        # ..and by him
-        nic.delete()
-        NetworkInterfaceFactory(network=net, ipv4="192.168.2.5",
-                                machine__userid="test_user")
-        request = {'pool': net.id, "address": "192.168.2.5"}
-        with mocked_quotaholder():
-            response = self.post(URL, "test_user", json.dumps(request), "json")
-        self.assertSuccess(response)
-
-        # Address out of pool
-        request = {'pool': net.id, "address": "192.168.3.5"}
-        with mocked_quotaholder():
-            response = self.post(URL, "test_user", json.dumps(request), "json")
-        self.assertBadRequest(response)
-
-    def test_release_in_use(self):
-        ip = FloatingIPFactory()
-        vm = ip.machine
-        vm.operstate = "ACTIVE"
-        vm.userid = ip.userid
-        vm.save()
-        vm.nics.create(index=0, ipv4=ip.ipv4, network=ip.network,
-                       state="ACTIVE")
-        with mocked_quotaholder():
-            response = self.delete(URL + "/%s" % ip.id, ip.userid)
-        self.assertFault(response, 409, "conflict")
-        # Also send a notification to remove the NIC and assert that FIP is in
-        # use until notification from ganeti arrives
-        request = {"removeFloatingIp": {"address": ip.ipv4}}
-        url = SERVERS_URL + "/%s/action" % vm.id
-        with patch('synnefo.logic.rapi_pool.GanetiRapiClient') as c:
-            c().ModifyInstance.return_value = 10
-            response = self.post(url, vm.userid, json.dumps(request),
-                                 "json")
-        self.assertEqual(response.status_code, 202)
-        with mocked_quotaholder():
-            response = self.delete(URL + "/%s" % ip.id, ip.userid)
-        self.assertFault(response, 409, "conflict")
-
-    def test_release(self):
-        ip = FloatingIPFactory(machine=None)
-        with mocked_quotaholder():
-            response = self.delete(URL + "/%s" % ip.id, ip.userid)
-        self.assertSuccess(response)
-        ips_after = FloatingIP.objects.filter(id=ip.id)
-        self.assertEqual(len(ips_after), 0)
-
-    @patch("synnefo.logic.backend", Mock())
-    def test_delete_network_with_floating_ips(self):
-        ip = FloatingIPFactory(machine=None, network__flavor="IP_LESS_ROUTED")
-        net = ip.network
-        # Can not remove network with floating IPs
-        with mocked_quotaholder():
-            response = self.delete(NETWORKS_URL + "/%s" % net.id,
-                                   net.userid)
-        self.assertFault(response, 421, "networkInUse")
-        # But we can with only deleted Floating Ips
-        ip.deleted = True
-        ip.save()
-        with mocked_quotaholder():
-            response = self.delete(NETWORKS_URL + "/%s" % net.id,
-                                   net.userid)
-        self.assertSuccess(response)
-
-
-POOLS_URL = join_urls(compute_path, "os-floating-ip-pools")
-
-
-class FloatingIPPoolsAPITest(BaseAPITest):
-    def test_no_pool(self):
-        response = self.get(POOLS_URL)
-        self.assertSuccess(response)
-        self.assertEqual(json.loads(response.content)["floating_ip_pools"], [])
-
-    def test_list_pools(self):
-        net = FloatingIPPoolFactory(subnet="192.168.0.0/30",
-                                    gateway="192.168.0.1")
-        NetworkFactory(public=True, deleted=True)
-        NetworkFactory(public=False, deleted=False)
-        NetworkFactory(public=True, deleted=False)
-        response = self.get(POOLS_URL)
-        self.assertSuccess(response)
-        self.assertEqual(json.loads(response.content)["floating_ip_pools"],
-                         [{"name": str(net.id), "size": 4, "free": 1}])
-
-
-class FloatingIPActionsTest(BaseAPITest):
-    def setUp(self):
-        vm = VirtualMachineFactory()
-        vm.operstate = "ACTIVE"
-        vm.save()
-        self.vm = vm
-
-    def test_bad_request(self):
-        url = SERVERS_URL + "/%s/action" % self.vm.id
-        response = self.post(url, self.vm.userid, json.dumps({}), "json")
-        self.assertBadRequest(response)
-        response = self.post(url, self.vm.userid,
-                             json.dumps({"addFloatingIp": {}}),
-                             "json")
-        self.assertBadRequest(response)
-
-    @patch('synnefo.logic.rapi_pool.GanetiRapiClient')
-    def test_add_floating_ip(self, mock):
-        # Not exists
-        url = SERVERS_URL + "/%s/action" % self.vm.id
-        request = {"addFloatingIp": {"address": "10.0.0.1"}}
-        response = self.post(url, self.vm.userid, json.dumps(request), "json")
-        self.assertItemNotFound(response)
-        # In use
-        vm1 = VirtualMachineFactory()
-        ip1 = FloatingIPFactory(userid=self.vm.userid, machine=vm1)
-        BackendNetworkFactory(network=ip1.network, backend=vm1.backend,
-                              operstate='ACTIVE')
-        request = {"addFloatingIp": {"address": ip1.ipv4}}
-        response = self.post(url, self.vm.userid, json.dumps(request), "json")
-        self.assertFault(response, 409, "conflict")
-        # Success
-        ip1 = FloatingIPFactory(userid=self.vm.userid, machine=None)
-        BackendNetworkFactory(network=ip1.network, backend=self.vm.backend,
-                              operstate='ACTIVE')
-        request = {"addFloatingIp": {"address": ip1.ipv4}}
-        mock().ModifyInstance.return_value = 1
-        response = self.post(url, self.vm.userid, json.dumps(request), "json")
-        self.assertEqual(response.status_code, 202)
-        ip1_after = FloatingIP.objects.get(id=ip1.id)
-        self.assertEqual(ip1_after.machine, self.vm)
-        self.assertTrue(ip1_after.in_use())
-        self.vm.nics.create(ipv4=ip1_after.ipv4, network=ip1_after.network,
-                            state="ACTIVE", index=0)
-        response = self.get(SERVERS_URL + "/%s" % self.vm.id,
-                            self.vm.userid)
-        self.assertSuccess(response)
-        nic = json.loads(response.content)["server"]["attachments"][0]
-        self.assertEqual(nic["OS-EXT-IPS:type"], "floating")
-
-    @patch('synnefo.logic.rapi_pool.GanetiRapiClient')
-    def test_remove_floating_ip(self, mock):
-        # Not exists
-        url = SERVERS_URL + "/%s/action" % self.vm.id
-        request = {"removeFloatingIp": {"address": "10.0.0.1"}}
-        response = self.post(url, self.vm.userid, json.dumps(request), "json")
-        self.assertItemNotFound(response)
-        # Not In Use
-        ip1 = FloatingIPFactory(userid=self.vm.userid, machine=None)
-        request = {"removeFloatingIp": {"address": ip1.ipv4}}
-        response = self.post(url, self.vm.userid, json.dumps(request), "json")
-        self.assertItemNotFound(response)
-        # Success
-        ip1 = FloatingIPFactory(userid=self.vm.userid, machine=self.vm)
-        NetworkInterfaceFactory(machine=self.vm, ipv4=ip1.ipv4)
-        request = {"removeFloatingIp": {"address": ip1.ipv4}}
-        mock().ModifyInstance.return_value = 2
-        response = self.post(url, self.vm.userid, json.dumps(request), "json")
-        self.assertEqual(response.status_code, 202)
-        # Yet used. Wait for the callbacks
-        ip1_after = FloatingIP.objects.get(id=ip1.id)
-        self.assertEqual(ip1_after.machine, self.vm)
-        self.assertTrue(ip1_after.in_use())
diff --git a/snf-cyclades-app/synnefo/api/test/images.py b/snf-cyclades-app/synnefo/api/test/images.py
deleted file mode 100644
index ff844d7..0000000
--- a/snf-cyclades-app/synnefo/api/test/images.py
+++ /dev/null
@@ -1,384 +0,0 @@
-# Copyright 2012 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.
-
-import json
-
-from snf_django.lib.api import faults
-from snf_django.utils.testing import BaseAPITest
-from synnefo.lib.services import get_service_path
-from synnefo.cyclades_settings import cyclades_services
-from synnefo.lib import join_urls
-
-from mock import patch
-from functools import wraps
-
-
-def assert_backend_closed(func):
-    """Decorator for ensuring that ImageBackend is returned to pool."""
-    @wraps(func)
-    def wrapper(self, backend):
-        result = func(self, backend)
-        if backend.called is True:
-            backend.return_value.close.asssert_called
-        return result
-    return wrapper
-
-
-class ComputeAPITest(BaseAPITest):
-    def setUp(self, *args, **kwargs):
-        super(ComputeAPITest, self).setUp(*args, **kwargs)
-        self.compute_path = get_service_path(cyclades_services, 'compute',
-                                             version='v2.0')
-    def myget(self, path, *args, **kwargs):
-        path = join_urls(self.compute_path, path)
-        return self.get(path, *args, **kwargs)
-
-    def myput(self, path, *args, **kwargs):
-        path = join_urls(self.compute_path, path)
-        return self.put(path, *args, **kwargs)
-
-    def mypost(self, path, *args, **kwargs):
-        path = join_urls(self.compute_path, path)
-        return self.post(path, *args, **kwargs)
-
-    def mydelete(self, path, *args, **kwargs):
-        path = join_urls(self.compute_path, path)
-        return self.delete(path, *args, **kwargs)
-
-
-@patch('synnefo.plankton.backend.ImageBackend')
-class ImageAPITest(ComputeAPITest):
-    @assert_backend_closed
-    def test_create_image(self, mimage):
-        """Test that create image is not implemented"""
-        response = self.mypost('images/', 'user', json.dumps(''), 'json')
-        self.assertEqual(response.status_code, 501)
-
-    @assert_backend_closed
-    def test_list_images(self, mimage):
-        """Test that expected list of images is returned"""
-        images = [{'id': 1, 'name': 'image-1'},
-                  {'id': 2, 'name': 'image-2'},
-                  {'id': 3, 'name': 'image-3'}]
-        mimage().list_images.return_value = images
-        response = self.myget('images', 'user')
-        self.assertSuccess(response)
-        api_images = json.loads(response.content)['images']
-        self.assertEqual(images, api_images)
-
-    @assert_backend_closed
-    def test_list_images_detail(self, mimage):
-        images = [{'id': 1,
-                   'name': 'image-1',
-                   'status':'available',
-                   'created_at': '2012-11-26 11:52:54',
-                   'updated_at': '2012-12-26 11:52:54',
-                   'owner': 'user1',
-                   'deleted_at': '',
-                   'properties': {'foo':'bar'}},
-                  {'id': 2,
-                   'name': 'image-2',
-                   'status': 'deleted',
-                   'created_at': '2012-11-26 11:52:54',
-                   'updated_at': '2012-12-26 11:52:54',
-                   'owner': 'user1',
-                   'deleted_at': '2012-12-27 11:52:54',
-                   'properties': ''},
-                  {'id': 3,
-                   'name': 'image-3',
-                   'status': 'available',
-                   'created_at': '2012-11-26 11:52:54',
-                   'deleted_at': '',
-                   'updated_at': '2012-12-26 11:52:54',
-                   'owner': 'user1',
-                   'properties': ''}]
-        result_images = [
-                  {'id': 1,
-                   'name': 'image-1',
-                   'status':'ACTIVE',
-                   'progress': 100,
-                   'created': '2012-11-26T11:52:54+00:00',
-                   'updated': '2012-12-26T11:52:54+00:00',
-                   'user_id': 'user1',
-                   'tenant_id': 'user1',
-                   'metadata': {'foo':'bar'}},
-                  {'id': 2,
-                   'name': 'image-2',
-                   'status': 'DELETED',
-                   'progress': 0,
-                   'user_id': 'user1',
-                   'tenant_id': 'user1',
-                   'created': '2012-11-26T11:52:54+00:00',
-                   'updated': '2012-12-26T11:52:54+00:00',
-                   'metadata': {}},
-                  {'id': 3,
-                   'name': 'image-3',
-                   'status': 'ACTIVE',
-                   'progress': 100,
-                   'user_id': 'user1',
-                   'tenant_id': 'user1',
-                   'created': '2012-11-26T11:52:54+00:00',
-                   'updated': '2012-12-26T11:52:54+00:00',
-                   'metadata': {}}]
-        mimage().list_images.return_value = images
-        response = self.myget('images/detail', 'user')
-        self.assertSuccess(response)
-        api_images = json.loads(response.content)['images']
-        self.assertEqual(len(result_images), len(api_images))
-        map(lambda image: image.pop("links"), api_images)
-        self.assertEqual(result_images, api_images)
-
-    @assert_backend_closed
-    def test_list_images_detail_since(self, mimage):
-        from datetime import datetime, timedelta
-        from time import sleep
-        old_time = datetime.now()
-        new_time = old_time + timedelta(seconds=0.1)
-        sleep(0.1)
-        images = [
-                  {'id': 1,
-                   'name': 'image-1',
-                   'status':'available',
-                   'progress': 100,
-                   'created_at': old_time.isoformat(),
-                   'deleted_at': '',
-                   'updated_at': old_time.isoformat(),
-                   'owner': 'user1',
-                   'properties': ''},
-                  {'id': 2,
-                   'name': 'image-2',
-                   'status': 'deleted',
-                   'progress': 0,
-                   'owner': 'user2',
-                   'created_at': new_time.isoformat(),
-                   'updated_at': new_time.isoformat(),
-                   'deleted_at': new_time.isoformat(),
-                   'properties': ''}]
-        mimage().list_images.return_value = images
-        response =\
-            self.myget('images/detail?changes-since=%sUTC' % new_time)
-        self.assertSuccess(response)
-        api_images = json.loads(response.content)['images']
-        self.assertEqual(1, len(api_images))
-
-    @assert_backend_closed
-    def test_get_image_details(self, mimage):
-        image = {'id': 42,
-                 'name': 'image-1',
-                 'status': 'available',
-                 'created_at': '2012-11-26 11:52:54',
-                 'updated_at': '2012-12-26 11:52:54',
-                 'deleted_at': '',
-                 'owner': 'user1',
-                 'properties': {'foo': 'bar'}}
-        result_image = \
-                  {'id': 42,
-                   'name': 'image-1',
-                   'status': 'ACTIVE',
-                   'progress': 100,
-                   'created': '2012-11-26T11:52:54+00:00',
-                   'updated': '2012-12-26T11:52:54+00:00',
-                   'user_id': 'user1',
-                   'tenant_id': 'user1',
-                   'metadata': {'foo': 'bar'}}
-        mimage.return_value.get_image.return_value = image
-        response = self.myget('images/42', 'user')
-        self.assertSuccess(response)
-        api_image = json.loads(response.content)['image']
-        api_image.pop("links")
-        self.assertEqual(api_image, result_image)
-
-    @assert_backend_closed
-    def test_invalid_image(self, mimage):
-        mimage.return_value.get_image.side_effect = faults.ItemNotFound('Image not found')
-        response = self.myget('images/42', 'user')
-        self.assertItemNotFound(response)
-
-    @assert_backend_closed
-    def test_delete_image(self, mimage):
-        response = self.mydelete("images/42", "user")
-        self.assertEqual(response.status_code, 204)
-        mimage.return_value.unregister.assert_called_once_with('42')
-        mimage.return_value._delete.assert_not_called('42')
-
-    @assert_backend_closed
-    def test_catch_wrong_api_paths(self, *args):
-        response = self.myget('nonexistent')
-        self.assertEqual(response.status_code, 400)
-        try:
-            error = json.loads(response.content)
-        except ValueError:
-            self.assertTrue(False)
-
-    @assert_backend_closed
-    def test_method_not_allowed(self, *args):
-        # /images/ allows only POST, GET
-        response = self.myput('images', '', '')
-        self.assertMethodNotAllowed(response)
-        response = self.mydelete('images')
-        self.assertMethodNotAllowed(response)
-
-        # /images/<imgid>/ allows only GET, DELETE
-        response = self.mypost("images/42")
-        self.assertMethodNotAllowed(response)
-        response = self.myput('images/42', '', '')
-        self.assertMethodNotAllowed(response)
-
-        # /images/<imgid>/metadata/ allows only POST, GET
-        response = self.myput('images/42/metadata', '', '')
-        self.assertMethodNotAllowed(response)
-        response = self.mydelete('images/42/metadata')
-        self.assertMethodNotAllowed(response)
-
-        # /images/<imgid>/metadata/ allows only POST, GET
-        response = self.myput('images/42/metadata', '', '')
-        self.assertMethodNotAllowed(response)
-        response = self.mydelete('images/42/metadata')
-        self.assertMethodNotAllowed(response)
-
-        # /images/<imgid>/metadata/<key> allows only PUT, GET, DELETE
-        response = self.mypost('images/42/metadata/foo')
-        self.assertMethodNotAllowed(response)
-
-
-@patch('synnefo.plankton.backend.ImageBackend')
-class ImageMetadataAPITest(ComputeAPITest):
-    def setUp(self):
-        self.image = {'id': 42,
-                 'name': 'image-1',
-                 'status': 'available',
-                 'created_at': '2012-11-26 11:52:54',
-                 'updated_at': '2012-12-26 11:52:54',
-                 'deleted_at': '',
-                 'properties': {'foo': 'bar', 'foo2': 'bar2'}}
-        self.result_image = \
-                  {'id': 42,
-                   'name': 'image-1',
-                   'status': 'ACTIVE',
-                   'progress': 100,
-                   'created': '2012-11-26T11:52:54+00:00',
-                   'updated': '2012-12-26T11:52:54+00:00',
-                   'metadata': {'foo': 'bar'}}
-        super(ImageMetadataAPITest, self).setUp()
-
-    @assert_backend_closed
-    def test_list_metadata(self, backend):
-        backend.return_value.get_image.return_value = self.image
-        response = self.myget('images/42/metadata', 'user')
-        self.assertSuccess(response)
-        meta = json.loads(response.content)['metadata']
-        self.assertEqual(meta, self.image['properties'])
-
-    @assert_backend_closed
-    def test_get_metadata(self, backend):
-        backend.return_value.get_image.return_value = self.image
-        response = self.myget('images/42/metadata/foo', 'user')
-        self.assertSuccess(response)
-        meta = json.loads(response.content)['meta']
-        self.assertEqual(meta['foo'], 'bar')
-
-    @assert_backend_closed
-    def test_get_invalid_metadata(self, backend):
-        backend.return_value.get_image.return_value = self.image
-        response = self.myget('images/42/metadata/not_found', 'user')
-        self.assertItemNotFound(response)
-
-    def test_delete_metadata_item(self, backend):
-        backend.return_value.get_image.return_value = self.image
-        response = self.mydelete('images/42/metadata/foo', 'user')
-        self.assertEqual(response.status_code, 204)
-        backend.return_value.update_metadata.assert_called_once_with('42', {'properties': {'foo2':
-                                                    'bar2'}})
-
-    @assert_backend_closed
-    def test_create_metadata_item(self, backend):
-        backend.return_value.get_image.return_value = self.image
-        request = {'meta': {'foo3': 'bar3'}}
-        response = self.myput('images/42/metadata/foo3', 'user',
-                              json.dumps(request), 'json')
-        self.assertEqual(response.status_code, 201)
-        backend.return_value.update_metadata.assert_called_once_with('42',
-                {'properties':
-                    {'foo': 'bar', 'foo2': 'bar2', 'foo3': 'bar3'}})
-
-    @assert_backend_closed
-    def test_create_metadata_malformed_1(self, backend):
-        backend.return_value.get_image.return_value = self.image
-        request = {'met': {'foo3': 'bar3'}}
-        response = self.myput('images/42/metadata/foo3', 'user',
-                              json.dumps(request), 'json')
-        self.assertBadRequest(response)
-
-    @assert_backend_closed
-    def test_create_metadata_malformed_2(self, backend):
-        backend.return_value.get_image.return_value = self.image
-        request = {'metadata': [('foo3', 'bar3')]}
-        response = self.myput('images/42/metadata/foo3', 'user',
-                              json.dumps(request), 'json')
-        self.assertBadRequest(response)
-
-    @assert_backend_closed
-    def test_create_metadata_malformed_3(self, backend):
-        backend.return_value.get_image.return_value = self.image
-        request = {'met': {'foo3': 'bar3', 'foo4': 'bar4'}}
-        response = self.myput('images/42/metadata/foo3', 'user',
-                                json.dumps(request), 'json')
-        self.assertBadRequest(response)
-
-    @assert_backend_closed
-    def test_create_metadata_malformed_4(self, backend):
-        backend.return_value.get_image.return_value = self.image
-        request = {'met': {'foo3': 'bar3'}}
-        response = self.myput('images/42/metadata/foo4', 'user',
-                              json.dumps(request), 'json')
-        self.assertBadRequest(response)
-
-    @assert_backend_closed
-    def test_update_metadata_item(self, backend):
-        backend.return_value.get_image.return_value = self.image
-        request = {'metadata': {'foo': 'bar_new', 'foo4': 'bar4'}}
-        response = self.mypost('images/42/metadata', 'user',
-                               json.dumps(request), 'json')
-        self.assertEqual(response.status_code, 201)
-        backend.return_value.update_metadata.assert_called_once_with('42',
-                {'properties':
-                    {'foo': 'bar_new', 'foo2': 'bar2', 'foo4': 'bar4'}
-                })
-
-    @assert_backend_closed
-    def test_update_metadata_malformed(self, backend):
-        backend.return_value.get_image.return_value = self.image
-        request = {'meta': {'foo': 'bar_new', 'foo4': 'bar4'}}
-        response = self.mypost('images/42/metadata', 'user',
-                               json.dumps(request), 'json')
-        self.assertBadRequest(response)
diff --git a/snf-cyclades-app/synnefo/api/test/networks.py b/snf-cyclades-app/synnefo/api/test/networks.py
deleted file mode 100644
index 8d2e661..0000000
--- a/snf-cyclades-app/synnefo/api/test/networks.py
+++ /dev/null
@@ -1,463 +0,0 @@
-# Copyright 2012 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.
-
-import json
-from mock import patch
-
-from snf_django.utils.testing import BaseAPITest, mocked_quotaholder
-from synnefo.db.models import Network, NetworkInterface
-from synnefo.db import models_factory as mfactory
-from synnefo.cyclades_settings import cyclades_services
-from synnefo.lib.services import get_service_path
-from synnefo.lib import join_urls
-
-
-class ComputeAPITest(BaseAPITest):
-    def __init__(self, *args, **kwargs):
-        super(ComputeAPITest, self).__init__(*args, **kwargs)
-        self.compute_path = get_service_path(cyclades_services, 'compute',
-                                             version='v2.0')
-
-    def myget(self, path, *args, **kwargs):
-        path = join_urls(self.compute_path, path)
-        return self.get(path, *args, **kwargs)
-
-    def myput(self, path, *args, **kwargs):
-        path = join_urls(self.compute_path, path)
-        return self.put(path, *args, **kwargs)
-
-    def mypost(self, path, *args, **kwargs):
-        path = join_urls(self.compute_path, path)
-        return self.post(path, *args, **kwargs)
-
-    def mydelete(self, path, *args, **kwargs):
-        path = join_urls(self.compute_path, path)
-        return self.delete(path, *args, **kwargs)
-
-
-@patch('synnefo.logic.rapi_pool.GanetiRapiClient')
-class NetworkAPITest(ComputeAPITest):
-    def setUp(self):
-        self.mac_prefixes = mfactory.MacPrefixPoolTableFactory()
-        self.bridges = mfactory.BridgePoolTableFactory(base="link")
-        self.user = 'dummy-user'
-        self.net1 = mfactory.NetworkFactory(userid=self.user)
-        self.vm1 = mfactory.VirtualMachineFactory(userid=self.user)
-        self.nic1 = mfactory.NetworkInterfaceFactory(network=self.net1,
-                                                     machine=self.vm1)
-        self.nic2 = mfactory.NetworkInterfaceFactory(network=self.net1,
-                                                     machine=self.vm1)
-        self.net2 = mfactory.NetworkFactory(userid=self.user)
-        self.nic3 = mfactory.NetworkInterfaceFactory(network=self.net2)
-        super(NetworkAPITest, self).setUp()
-
-    def assertNetworksEqual(self, db_net, api_net, detail=False):
-        self.assertEqual(str(db_net.id), api_net["id"])
-        self.assertEqual(db_net.name, api_net['name'])
-        if detail:
-            self.assertEqual(db_net.state, api_net['status'])
-            self.assertEqual(db_net.flavor, api_net['type'])
-            self.assertEqual(db_net.subnet, api_net['cidr'])
-            self.assertEqual(db_net.subnet6, api_net['cidr6'])
-            self.assertEqual(db_net.gateway, api_net['gateway'])
-            self.assertEqual(db_net.gateway6, api_net['gateway6'])
-            self.assertEqual(db_net.dhcp, api_net['dhcp'])
-            self.assertEqual(db_net.public, api_net['public'])
-            db_nics = ["nic-%d-%d" % (nic.machine.id, nic.index) for nic in
-                       db_net.nics.filter(machine__userid=db_net.userid)]
-            self.assertEqual(db_nics, api_net['attachments'])
-
-    def test_create_network_1(self, mrapi):
-        request = {
-            'network': {'name': 'foo', "type": "MAC_FILTERED"}
-        }
-        with mocked_quotaholder():
-            response = self.mypost('networks/', 'user1',
-                                   json.dumps(request), 'json')
-        self.assertEqual(response.status_code, 202)
-        db_networks = Network.objects.filter(userid='user1')
-        self.assertEqual(len(db_networks), 1)
-        db_net = db_networks[0]
-        api_net = json.loads(response.content)['network']
-        self.assertNetworksEqual(db_net, api_net)
-        mrapi.CreateNetwork.assert_called()
-        mrapi.ConnectNetwork.assert_called()
-
-    def test_invalid_data_1(self, mrapi):
-        """Test invalid flavor"""
-        request = {
-            'network': {'name': 'foo', 'type': 'LoLo'}
-            }
-        response = self.mypost('networks/', 'user1',
-                               json.dumps(request), 'json')
-        self.assertBadRequest(response)
-        self.assertEqual(len(Network.objects.filter(userid='user1')), 0)
-
-    def test_invalid_data_2(self, mrapi):
-        """Test invalid data/subnet"""
-        request = {
-            'network': {'name': 'foo',
-                        'cidr': '10.0.0.0/8', "type":
-                        "MAC_FILTERED"}
-        }
-        response = self.mypost('networks/', 'user1',
-                               json.dumps(request), 'json')
-        self.assertFault(response, 413, "overLimit")
-
-    def test_invalid_data_3(self, mrapi):
-        """Test unauthorized to create public network"""
-        request = {
-                'network': {'name': 'foo',
-                            "public": "True",
-                            "type": "MAC_FILTERED"}
-            }
-        response = self.mypost('networks/', 'user1',
-                               json.dumps(request), 'json')
-        self.assertFault(response, 403, "forbidden")
-
-    def test_invalid_data_4(self, mrapi):
-        """Test unauthorized to create network not in settings"""
-        request = {
-                'network': {'name': 'foo', 'type': 'CUSTOM'}
-            }
-        response = self.mypost('networks/', 'user1',
-                               json.dumps(request), 'json')
-        self.assertFault(response, 403, "forbidden")
-
-    def test_invalid_subnet(self, mrapi):
-        """Test invalid subnet"""
-        request = {
-            'network': {'name': 'foo',
-                        'cidr': '10.0.0.10/27',
-                        "type": "MAC_FILTERED"}
-        }
-        response = self.mypost('networks/', 'user1',
-                               json.dumps(request), 'json')
-        self.assertBadRequest(response)
-
-    def test_invalid_gateway_1(self, mrapi):
-        request = {
-            'network': {'name': 'foo',
-                        'cidr': '10.0.0.0/28',
-                        'gateway': '10.0.0.0.300'}
-        }
-        response = self.mypost('networks/', 'user1',
-                               json.dumps(request), 'json')
-        self.assertBadRequest(response)
-
-    def test_invalid_gateway_2(self, mrapi):
-        request = {
-            'network': {'name': 'foo',
-                        'cidr': '10.0.0.0/28',
-                        'gateway': '10.2.0.1'}
-        }
-        response = self.mypost('networks/', 'user1',
-                               json.dumps(request), 'json')
-        self.assertBadRequest(response)
-
-    def test_invalid_network6(self, mrapi):
-        request = {
-            'network': {'name': 'foo',
-                        'cidr': '10.0.0.0/28',
-                        'subnet6': '10.0.0.0/28',
-                        'gateway': '10.2.0.1'}
-        }
-        response = self.mypost('networks/', 'user1',
-                               json.dumps(request), 'json')
-        self.assertBadRequest(response)
-
-    def test_invalid_gateway6(self, mrapi):
-        request = {
-            'network': {'name': 'foo',
-                        'cidr': '10.0.0.0/28',
-                        'subnet6': '2001:0db8:0123:4567:89ab:cdef:1234:5678',
-                        'gateway': '10.2.0.1'}
-        }
-        response = self.mypost('networks/', 'user1',
-                               json.dumps(request), 'json')
-        self.assertBadRequest(response)
-
-    def test_list_networks(self, mrapi):
-        """Test that expected list of networks is returned."""
-        # Create a deleted network
-        mfactory.NetworkFactory(userid=self.user, deleted=True)
-
-        response = self.myget('networks/', self.user)
-        self.assertSuccess(response)
-
-        db_nets = Network.objects.filter(userid=self.user, deleted=False)
-        api_nets = json.loads(response.content)["networks"]
-
-        self.assertEqual(len(db_nets), len(api_nets))
-        for api_net in api_nets:
-            net_id = api_net['id']
-            self.assertNetworksEqual(Network.objects.get(id=net_id), api_net)
-
-    def test_list_networks_detail(self, mrapi):
-        """Test that expected networks details are returned."""
-        # Create a deleted network
-        mfactory.NetworkFactory(userid=self.user, deleted=True)
-
-        response = self.myget('networks/detail', self.user)
-        self.assertSuccess(response)
-
-        db_nets = Network.objects.filter(userid=self.user, deleted=False)
-        api_nets = json.loads(response.content)["networks"]
-
-        self.assertEqual(len(db_nets), len(api_nets))
-        for api_net in api_nets:
-            net_id = api_net['id']
-            self.assertNetworksEqual(Network.objects.get(id=net_id), api_net,
-                                     detail=True)
-
-    def test_get_network_building_nics(self, mrapi):
-        net = mfactory.NetworkFactory()
-        machine = mfactory.VirtualMachineFactory(userid=net.userid)
-        mfactory.NetworkInterfaceFactory(network=net, machine=machine,
-                                         state="BUILDING")
-        response = self.myget('networks/%d' % net.id, net.userid)
-        self.assertSuccess(response)
-        api_net = json.loads(response.content)["network"]
-        self.assertEqual(len(api_net["attachments"]), 0)
-
-    def test_network_details_1(self, mrapi):
-        """Test that expected details for a network are returned"""
-        response = self.myget('networks/%d' % self.net1.id, self.net1.userid)
-        self.assertSuccess(response)
-        api_net = json.loads(response.content)["network"]
-        self.assertNetworksEqual(self.net1, api_net, detail=True)
-
-    def test_invalid_network(self, mrapi):
-        """Test details for non-existing network."""
-        response = self.myget('networks/%d' % 42, self.net1.userid)
-        self.assertItemNotFound(response)
-
-    def test_rename_network(self, mrapi):
-        request = {'network': {'name': "new_name"}}
-        response = self.myput('networks/%d' % self.net2.id,
-                              self.net2.userid, json.dumps(request), 'json')
-        self.assertEqual(response.status_code, 204)
-        self.assertEqual(Network.objects.get(id=self.net2.id).name, "new_name")
-        # Check invalid
-        request = {'name': "new_name"}
-        response = self.myput('networks/%d' % self.net2.id,
-                              self.net2.userid, json.dumps(request), 'json')
-        self.assertBadRequest(response)
-
-    def test_rename_deleted_network(self, mrapi):
-        net = mfactory.NetworkFactory(deleted=True)
-        request = {'network': {'name': "new_name"}}
-        response = self.myput('networks/%d' % net.id,
-                              net.userid, json.dumps(request), 'json')
-        self.assertBadRequest(response)
-
-    def test_rename_public_network(self, mrapi):
-        net = mfactory.NetworkFactory(public=True)
-        request = {'network': {'name': "new_name"}}
-        response = self.myput('networks/%d' % net.id,
-                              self.net2.userid, json.dumps(request), 'json')
-        self.assertFault(response, 403, 'forbidden')
-
-    def test_delete_network(self, mrapi):
-        net = mfactory.NetworkFactory(deleted=False, state='ACTIVE',
-                                      link="link-10")
-        with mocked_quotaholder():
-            response = self.mydelete('networks/%d' % net.id, net.userid)
-        self.assertEqual(response.status_code, 204)
-        net = Network.objects.get(id=net.id, userid=net.userid)
-        self.assertEqual(net.action, 'DESTROY')
-        mrapi.DeleteNetwork.assert_called()
-
-    def test_delete_public_network(self, mrapi):
-        net = mfactory.NetworkFactory(public=True)
-        response = self.mydelete('networks/%d' % net.id, self.net2.userid)
-        self.assertFault(response, 403, 'forbidden')
-        self.assertFalse(mrapi.called)
-
-    def test_delete_deleted_network(self, mrapi):
-        net = mfactory.NetworkFactory(deleted=True)
-        response = self.mydelete('networks/%d' % net.id, net.userid)
-        self.assertBadRequest(response)
-
-    def test_delete_network_in_use(self, mrapi):
-        net = self.net1
-        response = self.mydelete('networks/%d' % net.id, net.userid)
-        self.assertFault(response, 421, 'networkInUse')
-        self.assertFalse(mrapi.called)
-
-    def test_add_nic(self, mrapi):
-        user = 'userr'
-        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
-        net = mfactory.NetworkFactory(state='ACTIVE', userid=user)
-        mrapi().ModifyInstance.return_value = 1
-        request = {'add': {'serverRef': vm.id}}
-        response = self.mypost('networks/%d/action' % net.id,
-                               net.userid, json.dumps(request), 'json')
-        self.assertEqual(response.status_code, 202)
-
-    def test_add_nic_to_deleted_network(self, mrapi):
-        user = 'userr'
-        vm = mfactory.VirtualMachineFactory(name='yo', userid=user,
-                                            operstate="ACTIVE")
-        net = mfactory.NetworkFactory(state='ACTIVE', userid=user,
-                                      deleted=True)
-        request = {'add': {'serverRef': vm.id}}
-        response = self.mypost('networks/%d/action' % net.id,
-                               net.userid, json.dumps(request), 'json')
-        self.assertBadRequest(response)
-        self.assertFalse(mrapi.called)
-
-    def test_add_nic_to_public_network(self, mrapi):
-        user = 'userr'
-        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
-        net = mfactory.NetworkFactory(state='ACTIVE', userid=user, public=True)
-        request = {'add': {'serverRef': vm.id}}
-        response = self.mypost('networks/%d/action' % net.id,
-                               net.userid, json.dumps(request), 'json')
-        self.assertFault(response, 403, 'forbidden')
-        self.assertFalse(mrapi.called)
-
-    def test_add_nic_malformed_1(self, mrapi):
-        user = 'userr'
-        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
-        net = mfactory.NetworkFactory(state='ACTIVE', userid=user)
-        request = {'add': {'serveRef': vm.id}}
-        response = self.mypost('networks/%d/action' % net.id,
-                               net.userid, json.dumps(request), 'json')
-        self.assertBadRequest(response)
-        self.assertFalse(mrapi.called)
-
-    def test_add_nic_malformed_2(self, mrapi):
-        user = 'userr'
-        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
-        net = mfactory.NetworkFactory(state='ACTIVE', userid=user)
-        request = {'add': {'serveRef': [vm.id, 22]}}
-        response = self.mypost('networks/%d/action' % net.id,
-                               net.userid, json.dumps(request), 'json')
-        self.assertBadRequest(response)
-        self.assertFalse(mrapi.called)
-
-    def test_add_nic_not_active(self, mrapi):
-        """Test connecting VM to non-active network"""
-        user = 'dummy'
-        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
-        net = mfactory.NetworkFactory(state='PENDING', subnet='10.0.0.0/31',
-                                      userid=user)
-        request = {'add': {'serverRef': vm.id}}
-        response = self.mypost('networks/%d/action' % net.id,
-                               net.userid, json.dumps(request), 'json')
-        # Test that returns BuildInProgress
-        self.assertEqual(response.status_code, 409)
-        self.assertFalse(mrapi.called)
-
-    def test_add_nic_full_network(self, mrapi):
-        """Test connecting VM to a full network"""
-        user = 'userr'
-        vm = mfactory.VirtualMachineFactory(name='yo', userid=user,
-                                            operstate="STARTED")
-        net = mfactory.NetworkFactory(state='ACTIVE', subnet='10.0.0.0/30',
-                                      userid=user, dhcp=True)
-        pool = net.get_pool()
-        while not pool.empty():
-            pool.get()
-        pool.save()
-        pool = net.get_pool()
-        self.assertTrue(pool.empty())
-        request = {'add': {'serverRef': vm.id}}
-        response = self.mypost('networks/%d/action' % net.id,
-                               net.userid, json.dumps(request), 'json')
-        # Test that returns OverLimit
-        self.assertEqual(response.status_code, 413)
-        self.assertFalse(mrapi.called)
-
-    def test_remove_nic(self, mrapi):
-        user = 'userr'
-        vm = mfactory.VirtualMachineFactory(name='yo', userid=user,
-                                            operstate="ACTIVE")
-        net = mfactory.NetworkFactory(state='ACTIVE', userid=user)
-        nic = mfactory.NetworkInterfaceFactory(machine=vm, network=net)
-        mrapi().ModifyInstance.return_value = 1
-        request = {'remove': {'attachment': 'nic-%s-%s' % (vm.id, nic.index)}}
-        response = self.mypost('networks/%d/action' % net.id,
-                               net.userid, json.dumps(request), 'json')
-        self.assertEqual(response.status_code, 202)
-        self.assertTrue(NetworkInterface.objects.get(id=nic.id).dirty)
-        vm.task = None
-        vm.task_job_id = None
-        vm.save()
-        # Remove dirty nic
-        response = self.mypost('networks/%d/action' % net.id,
-                               net.userid, json.dumps(request), 'json')
-        self.assertFault(response, 409, 'buildInProgress')
-
-    def test_remove_nic_malformed(self, mrapi):
-        user = 'userr'
-        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
-        net = mfactory.NetworkFactory(state='ACTIVE', userid=user)
-        nic = mfactory.NetworkInterfaceFactory(machine=vm, network=net)
-        request = {'remove':
-                    {'att234achment': 'nic-%s-%s' % (vm.id, nic.index)}
-                  }
-        response = self.mypost('networks/%d/action' % net.id,
-                               net.userid, json.dumps(request), 'json')
-        self.assertBadRequest(response)
-
-    def test_remove_nic_malformed_2(self, mrapi):
-        user = 'userr'
-        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
-        net = mfactory.NetworkFactory(state='ACTIVE', userid=user)
-        request = {'remove':
-                    {'attachment': 'nic-%s' % vm.id}
-                  }
-        response = self.mypost('networks/%d/action' % net.id,
-                               net.userid, json.dumps(request), 'json')
-        self.assertBadRequest(response)
-
-    def test_catch_wrong_api_paths(self, *args):
-        response = self.myget('nonexistent')
-        self.assertEqual(response.status_code, 400)
-        try:
-            error = json.loads(response.content)
-        except ValueError:
-            self.assertTrue(False)
-
-    def test_method_not_allowed(self, *args):
-        # /networks/ allows only POST, GET
-        response = self.myput('networks', '', '')
-        self.assertMethodNotAllowed(response)
-        response = self.mydelete('networks')
-        self.assertMethodNotAllowed(response)
-
-        # /networks/<srvid>/ allows only GET, PUT, DELETE
-        response = self.mypost("networks/42")
-        self.assertMethodNotAllowed(response)
diff --git a/snf-cyclades-app/synnefo/api/test/servers.py b/snf-cyclades-app/synnefo/api/test/servers.py
deleted file mode 100644
index 3aa8b48..0000000
--- a/snf-cyclades-app/synnefo/api/test/servers.py
+++ /dev/null
@@ -1,683 +0,0 @@
-# Copyright 2012 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.
-
-import json
-from copy import deepcopy
-
-from snf_django.utils.testing import (BaseAPITest, mocked_quotaholder,
-                                      override_settings)
-from synnefo.db.models import (VirtualMachine, VirtualMachineMetadata,
-                               FloatingIP)
-from synnefo.db import models_factory as mfactory
-from synnefo.logic.utils import get_rsapi_state
-from synnefo.cyclades_settings import cyclades_services
-from synnefo.lib.services import get_service_path
-from synnefo.lib import join_urls
-from synnefo import settings
-
-from mock import patch, Mock
-
-
-class ComputeAPITest(BaseAPITest):
-    def __init__(self, *args, **kwargs):
-        super(ComputeAPITest, self).__init__(*args, **kwargs)
-        self.compute_path = get_service_path(cyclades_services, 'compute',
-                                             version='v2.0')
-
-    def myget(self, path, *args, **kwargs):
-        path = join_urls(self.compute_path, path)
-        return self.get(path, *args, **kwargs)
-
-    def myput(self, path, *args, **kwargs):
-        path = join_urls(self.compute_path, path)
-        return self.put(path, *args, **kwargs)
-
-    def mypost(self, path, *args, **kwargs):
-        path = join_urls(self.compute_path, path)
-        return self.post(path, *args, **kwargs)
-
-    def mydelete(self, path, *args, **kwargs):
-        path = join_urls(self.compute_path, path)
-        return self.delete(path, *args, **kwargs)
-
-
-class ServerAPITest(ComputeAPITest):
-    def setUp(self):
-        self.user1 = 'user1'
-        self.user2 = 'user2'
-        self.vm1 = mfactory.VirtualMachineFactory(userid=self.user1)
-        self.vm2 = mfactory.VirtualMachineFactory(userid=self.user2)
-        self.vm3 = mfactory.VirtualMachineFactory(deleted=True,
-                                                  userid=self.user1)
-        self.vm4 = mfactory.VirtualMachineFactory(userid=self.user2)
-
-    def test_server_list_1(self):
-        """Test if the expected list of servers is returned."""
-        response = self.myget('servers')
-        self.assertSuccess(response)
-        servers = json.loads(response.content)['servers']
-        self.assertEqual(servers, [])
-
-    def test_server_list_2(self):
-        """Test if the expected list of servers is returned."""
-        response = self.myget('servers', self.user1)
-        self.assertSuccess(response)
-        servers = json.loads(response.content)['servers']
-        db_server = self.vm1
-        server = servers[0]
-        self.assertEqual(server["name"], db_server.name)
-        self.assertEqual(server["id"], db_server.id)
-
-    def test_server_list_detail(self):
-        """Test if the servers list details are returned."""
-        user = self.user2
-        user_vms = {self.vm2.id: self.vm2,
-                    self.vm4.id: self.vm4}
-
-        response = self.myget('servers/detail', user)
-        servers = json.loads(response.content)['servers']
-        self.assertEqual(len(servers), len(user_vms))
-        for api_vm in servers:
-            db_vm = user_vms[api_vm['id']]
-            self.assertEqual(api_vm['flavor']["id"], db_vm.flavor.id)
-            self.assertEqual(api_vm['hostId'], db_vm.hostid)
-            self.assertEqual(api_vm['id'], db_vm.id)
-            self.assertEqual(api_vm['image']["id"], db_vm.imageid)
-            self.assertEqual(api_vm['name'], db_vm.name)
-            self.assertEqual(api_vm['status'], get_rsapi_state(db_vm))
-            self.assertSuccess(response)
-
-    def test_server_detail(self):
-        """Test if a server details are returned."""
-        db_vm = self.vm2
-        user = self.vm2.userid
-        net = mfactory.NetworkFactory()
-        nic = mfactory.NetworkInterfaceFactory(machine=self.vm2, network=net,
-                                              ipv6="::babe")
-
-        db_vm_meta = mfactory.VirtualMachineMetadataFactory(vm=db_vm)
-
-        response = self.myget('servers/%d' % db_vm.id, user)
-        server = json.loads(response.content)['server']
-
-        self.assertEqual(server['flavor']["id"], db_vm.flavor.id)
-        self.assertEqual(server['hostId'], db_vm.hostid)
-        self.assertEqual(server['id'], db_vm.id)
-        self.assertEqual(server['image']["id"], db_vm.imageid)
-        self.assertEqual(server['name'], db_vm.name)
-        self.assertEqual(server['status'], get_rsapi_state(db_vm))
-        api_nic = server['attachments'][0]
-        self.assertEqual(api_nic['network_id'], str(net.id))
-        self.assertEqual(api_nic['mac_address'], nic.mac)
-        self.assertEqual(api_nic['firewallProfile'], nic.firewall_profile)
-        self.assertEqual(api_nic['ipv4'], nic.ipv4)
-        self.assertEqual(api_nic['ipv6'], nic.ipv6)
-        self.assertEqual(api_nic['OS-EXT-IPS:type'],"fixed")
-        self.assertEqual(api_nic['id'], 'nic-%s-%s' % (db_vm.id, nic.index))
-        api_address = server["addresses"]
-        self.assertEqual(api_address[str(net.id)],
-               [{"version": 4, "addr": nic.ipv4, "OS-EXT-IPS:type": "fixed"},
-                {"version": 6, "addr": nic.ipv6, "OS-EXT-IPS:type": "fixed"}])
-
-        metadata = server['metadata']
-        self.assertEqual(len(metadata), 1)
-        self.assertEqual(metadata[db_vm_meta.meta_key], db_vm_meta.meta_value)
-        self.assertSuccess(response)
-
-    def test_server_building_nics(self):
-        db_vm = self.vm2
-        user = self.vm2.userid
-        net1 = mfactory.NetworkFactory()
-        net2 = mfactory.NetworkFactory()
-        net3 = mfactory.NetworkFactory()
-        mfactory.NetworkInterfaceFactory(machine=self.vm2, network=net1,
-                                         state="BUILDING")
-        nic2 = mfactory.NetworkInterfaceFactory(machine=self.vm2, network=net2,
-                                                state="ACTIVE")
-        mfactory.NetworkInterfaceFactory(machine=self.vm2, network=net3,
-                                         state="BUILDING")
-
-        response = self.myget('servers/%d' % db_vm.id, user)
-        server = json.loads(response.content)['server']
-        nics = server["attachments"]
-        self.assertEqual(len(nics), 1)
-        self.assertEqual(nics[0]["network_id"], str(nic2.network_id))
-
-    def test_noauthorized(self):
-        """Test 404 for detail of other user vm"""
-        db_vm = self.vm2
-
-        response = self.myget('servers/%d' % db_vm.id, 'wrong_user')
-        self.assertItemNotFound(response)
-
-    def test_wrong_server(self):
-        """Test 404 response if server does not exist."""
-        response = self.myget('servers/%d' % 5000)
-        self.assertItemNotFound(response)
-
-    def test_create_server_empty(self):
-        """Test if the create server call returns a 400 badRequest if
-           no attributes are specified."""
-
-        response = self.mypost('servers', params={})
-        self.assertBadRequest(response)
-
-    def test_rename_server(self):
-        vm = self.vm2
-        request = {'server': {'name': 'new_name'}}
-        response = self.myput('servers/%d' % vm.id, vm.userid,
-                              json.dumps(request), 'json')
-        self.assertSuccess(response)
-        self.assertEqual(VirtualMachine.objects.get(id=vm.id).name, "new_name")
-
-    def test_catch_wrong_api_paths(self):
-        response = self.myget('nonexistent')
-        self.assertEqual(response.status_code, 400)
-        try:
-            error = json.loads(response.content)
-        except ValueError:
-            self.assertTrue(False)
-
-    def test_method_not_allowed(self, *args):
-        # /servers/ allows only POST, GET
-        response = self.myput('servers', '', '')
-        self.assertMethodNotAllowed(response)
-        response = self.mydelete('servers')
-        self.assertMethodNotAllowed(response)
-
-        # /servers/<srvid>/ allows only GET, PUT, DELETE
-        response = self.mypost("servers/42")
-        self.assertMethodNotAllowed(response)
-
-        # /imags/<srvid>/metadata/ allows only POST, GET
-        response = self.myput('servers/42/metadata', '', '')
-        self.assertMethodNotAllowed(response)
-        response = self.mydelete('servers/42/metadata')
-        self.assertMethodNotAllowed(response)
-
-        # /imags/<srvid>/metadata/ allows only POST, GET
-        response = self.myput('servers/42/metadata', '', '')
-        self.assertMethodNotAllowed(response)
-        response = self.mydelete('servers/42/metadata')
-        self.assertMethodNotAllowed(response)
-
-        # /imags/<srvid>/metadata/<key> allows only PUT, GET, DELETE
-        response = self.mypost('servers/42/metadata/foo')
-        self.assertMethodNotAllowed(response)
-
-
-fixed_image = Mock()
-fixed_image.return_value = {'location': 'pithos://foo',
-                            'checksum': '1234',
-                            "id": 1,
-                            "name": "test_image",
-                            'disk_format': 'diskdump'}
-
-
-@patch('synnefo.api.util.get_image', fixed_image)
-@patch('synnefo.logic.rapi_pool.GanetiRapiClient')
-class ServerCreateAPITest(ComputeAPITest):
-    def setUp(self):
-        self.flavor = mfactory.FlavorFactory()
-        # Create public network and backend
-        self.network = mfactory.NetworkFactory(public=True)
-        self.backend = mfactory.BackendFactory()
-        mfactory.BackendNetworkFactory(network=self.network,
-                                       backend=self.backend,
-                                       operstate="ACTIVE")
-        self.request = {
-                    "server": {
-                        "name": "new-server-test",
-                        "userid": "test_user",
-                        "imageRef": 1,
-                        "flavorRef": self.flavor.id,
-                        "metadata": {
-                            "My Server Name": "Apache1"
-                        },
-                        "personality": []
-                    }
-        }
-
-    def test_create_server(self, mrapi):
-        """Test if the create server call returns the expected response
-           if a valid request has been speficied."""
-
-        mrapi().CreateInstance.return_value = 12
-        with override_settings(settings, DEFAULT_INSTANCE_NETWORKS=[]):
-            with mocked_quotaholder():
-                response = self.mypost('servers', 'test_user',
-                                       json.dumps(self.request), 'json')
-        self.assertEqual(response.status_code, 202)
-        mrapi().CreateInstance.assert_called_once()
-
-        api_server = json.loads(response.content)['server']
-        self.assertEqual(api_server['status'], "BUILD")
-        self.assertEqual(api_server['progress'], 0)
-        self.assertEqual(api_server['metadata'],
-                        {"My Server Name":  "Apache1"})
-        self.assertTrue('adminPass' in api_server)
-
-        db_vm = VirtualMachine.objects.get(userid='test_user')
-        self.assertEqual(api_server['name'], db_vm.name)
-        self.assertEqual(api_server['status'], db_vm.operstate)
-
-        # Test drained flag in Network:
-        self.network.drained = True
-        self.network.save()
-        with mocked_quotaholder():
-            response = self.mypost('servers', 'test_user',
-                                   json.dumps(self.request), 'json')
-        self.assertEqual(response.status_code, 503, "serviceUnavailable")
-
-    def test_create_network_settings(self, mrapi):
-        mrapi().CreateInstance.return_value = 12
-        bnet1 = mfactory.BackendNetworkFactory(operstate="ACTIVE",
-                                               backend=self.backend)
-        bnet2 = mfactory.BackendNetworkFactory(operstate="ACTIVE",
-                                               backend=self.backend)
-        bnet3 = mfactory.BackendNetworkFactory(network__userid="test_user",
-                                               operstate="ACTIVE",
-                                               backend=self.backend)
-        bnet4 = mfactory.BackendNetworkFactory(network__userid="test_user",
-                                               operstate="ACTIVE",
-                                               backend=self.backend)
-        # User requested private networks
-        request = deepcopy(self.request)
-        request["server"]["networks"] = [bnet3.network.id, bnet4.network.id]
-        with override_settings(settings,
-                DEFAULT_INSTANCE_NETWORKS=["SNF:ANY_PUBLIC", bnet1.network.id,
-                                           bnet2.network.id]):
-            with mocked_quotaholder():
-                response = self.mypost('servers', 'test_user',
-                                       json.dumps(request), 'json')
-        self.assertEqual(response.status_code, 202)
-        name, args, kwargs = mrapi().CreateInstance.mock_calls[0]
-        self.assertEqual(len(kwargs["nics"]), 5)
-        self.assertEqual(kwargs["nics"][0]["network"],
-                         self.network.backend_id)
-        self.assertEqual(kwargs["nics"][1]["network"],
-                         bnet1.network.backend_id)
-        self.assertEqual(kwargs["nics"][2]["network"],
-                         bnet2.network.backend_id)
-        self.assertEqual(kwargs["nics"][3]["network"],
-                         bnet3.network.backend_id)
-        self.assertEqual(kwargs["nics"][4]["network"],
-                         bnet4.network.backend_id)
-
-        request["server"]["floating_ips"] = []
-        with override_settings(settings,
-                DEFAULT_INSTANCE_NETWORKS=[bnet2.network.id]):
-            with mocked_quotaholder():
-                response = self.mypost('servers', 'test_user',
-                                       json.dumps(request), 'json')
-        self.assertEqual(response.status_code, 202)
-        name, args, kwargs = mrapi().CreateInstance.mock_calls[1]
-        self.assertEqual(len(kwargs["nics"]), 3)
-        self.assertEqual(kwargs["nics"][0]["network"],
-                         bnet2.network.backend_id)
-        self.assertEqual(kwargs["nics"][1]["network"],
-                         bnet3.network.backend_id)
-        self.assertEqual(kwargs["nics"][2]["network"],
-                         bnet4.network.backend_id)
-
-        # test invalid network in DEFAULT_INSTANCE_NETWORKS
-        with override_settings(settings, DEFAULT_INSTANCE_NETWORKS=[42]):
-            response = self.mypost('servers', 'test_user',
-                                   json.dumps(request), 'json')
-        self.assertFault(response, 500, "internalServerError")
-
-        # test connect to public netwok
-        request = deepcopy(self.request)
-        request["server"]["networks"] = [self.network.id]
-        with override_settings(settings,
-                               DEFAULT_INSTANCE_NETWORKS=["SNF:ANY_PUBLIC"]):
-            response = self.mypost('servers', 'test_user',
-                                    json.dumps(request), 'json')
-        self.assertFault(response, 403, "forbidden")
-        # test wrong user
-        request = deepcopy(self.request)
-        request["server"]["networks"] = [bnet3.network.id]
-        with override_settings(settings,
-                               DEFAULT_INSTANCE_NETWORKS=["SNF:ANY_PUBLIC"]):
-            with mocked_quotaholder():
-                response = self.mypost('servers', 'dummy_user',
-                                       json.dumps(request), 'json')
-        self.assertItemNotFound(response)
-
-        # Test floating IPs
-        request = deepcopy(self.request)
-        request["server"]["networks"] = [bnet4.network.id]
-        network = mfactory.NetworkFactory(subnet="10.0.0.0/24")
-        mfactory.BackendNetworkFactory(network=network,
-                                       backend=self.backend,
-                                       operstate="ACTIVE")
-        fp1 = mfactory.FloatingIPFactory(ipv4="10.0.0.2",
-                                         userid="test_user",
-                                         network=network, machine=None)
-        fp2 = mfactory.FloatingIPFactory(ipv4="10.0.0.3", network=network,
-                                         userid="test_user",
-                                         machine=None)
-        request["server"]["floating_ips"] = [fp1.ipv4, fp2.ipv4]
-        with override_settings(settings,
-                DEFAULT_INSTANCE_NETWORKS=[bnet3.network.id]):
-            with mocked_quotaholder():
-                response = self.mypost('servers', 'test_user',
-                                     json.dumps(request), 'json')
-        self.assertEqual(response.status_code, 202)
-        api_server = json.loads(response.content)['server']
-        vm = VirtualMachine.objects.get(id=api_server["id"])
-        fp1 = FloatingIP.objects.get(id=fp1.id)
-        fp2 = FloatingIP.objects.get(id=fp2.id)
-        self.assertEqual(fp1.machine, vm)
-        self.assertEqual(fp2.machine, vm)
-        name, args, kwargs = mrapi().CreateInstance.mock_calls[2]
-        self.assertEqual(len(kwargs["nics"]), 4)
-        self.assertEqual(kwargs["nics"][0]["network"],
-                         bnet3.network.backend_id)
-        self.assertEqual(kwargs["nics"][1]["network"], network.backend_id)
-        self.assertEqual(kwargs["nics"][1]["ip"], fp1.ipv4)
-        self.assertEqual(kwargs["nics"][2]["network"], network.backend_id)
-        self.assertEqual(kwargs["nics"][2]["ip"], fp2.ipv4)
-        self.assertEqual(kwargs["nics"][3]["network"],
-                         bnet4.network.backend_id)
-
-    def test_create_server_no_flavor(self, mrapi):
-        request = deepcopy(self.request)
-        request["server"]["flavorRef"] = 42
-        with mocked_quotaholder():
-            response = self.mypost('servers', 'test_user',
-                                   json.dumps(request), 'json')
-        self.assertItemNotFound(response)
-
-
-@patch('synnefo.logic.rapi_pool.GanetiRapiClient')
-class ServerDestroyAPITest(ComputeAPITest):
-    def test_delete_server(self, mrapi):
-        vm = mfactory.VirtualMachineFactory()
-        mrapi().DeleteInstance.return_value = 12
-        response = self.mydelete('servers/%d' % vm.id, vm.userid)
-        self.assertEqual(response.status_code, 204)
-        mrapi().DeleteInstance.assert_called_once()
-
-    def test_non_existing_delete_server(self, mrapi):
-        vm = mfactory.VirtualMachineFactory()
-        response = self.mydelete('servers/%d' % 42, vm.userid)
-        self.assertItemNotFound(response)
-        self.assertFalse(mrapi.mock_calls)
-
-
-class ServerMetadataAPITest(ComputeAPITest):
-    def setUp(self):
-        self.vm = mfactory.VirtualMachineFactory()
-        self.metadata = mfactory.VirtualMachineMetadataFactory(vm=self.vm)
-        super(ServerMetadataAPITest, self).setUp()
-
-    def test_get_metadata(self):
-        vm = self.vm
-        create_meta = lambda: mfactory.VirtualMachineMetadataFactory(vm=vm)
-        metadata = [create_meta(), create_meta(), create_meta()]
-        response = self.myget('servers/%d/metadata' % vm.id, vm.userid)
-        self.assertTrue(response.status_code in [200, 203])
-        api_metadata = json.loads(response.content)['metadata']
-        self.assertEqual(len(api_metadata), len(metadata) + 1)
-        for db_m in metadata:
-            self.assertEqual(api_metadata[db_m.meta_key], db_m.meta_value)
-
-        request = {'metadata':
-                        {'foo': 'bar'},
-                        metadata[0].meta_key: 'bar2'
-                  }
-        response = self.mypost('servers/%d/metadata' % vm.id,
-                             vm.userid, json.dumps(request), 'json')
-        metadata2 = VirtualMachineMetadata.objects.filter(vm=vm)
-        response = self.myget('servers/%d/metadata' % vm.id, vm.userid)
-        self.assertTrue(response.status_code in [200, 203])
-        api_metadata2 = json.loads(response.content)['metadata']
-        self.assertTrue('foo' in api_metadata2.keys())
-        self.assertTrue(api_metadata2[metadata[0].meta_key], 'bar2')
-        self.assertEqual(len(api_metadata2), len(metadata2))
-        for db_m in metadata2:
-            self.assertEqual(api_metadata2[db_m.meta_key], db_m.meta_value)
-
-        # Create new meta
-        request = {'meta': {'foo2': 'bar2'}}
-        response = self.myput('servers/%d/metadata/foo2' % vm.id,
-                              vm.userid, json.dumps(request), 'json')
-
-        # Get the new meta
-        response = self.myget('servers/%d/metadata/foo2' % vm.id, vm.userid)
-        meta = json.loads(response.content)['meta']
-        self.assertEqual(meta['foo2'], 'bar2')
-
-        # Delete the new meta
-        response = self.mydelete('servers/%d/metadata/foo2' % vm.id, vm.userid)
-        self.assertEqual(response.status_code, 204)
-
-        # Try to get the deleted meta: should raise 404
-        response = self.myget('servers/%d/metadata/foo2' % vm.id, vm.userid)
-        self.assertEqual(response.status_code, 404)
-
-    def test_invalid_metadata(self):
-        vm = self.vm
-        response = self.mypost('servers/%d/metadata' % vm.id, vm.userid)
-        self.assertBadRequest(response)
-        self.assertEqual(len(vm.metadata.all()), 1)
-
-    def test_invalid_metadata_server(self):
-        response = self.mypost('servers/42/metadata', 'user')
-        self.assertItemNotFound(response)
-
-    def test_get_meta_invalid_key(self):
-        vm = self.vm
-        response = self.myget('servers/%d/metadata/foo2' % vm.id, vm.userid)
-        self.assertItemNotFound(response)
-
-
-@patch('synnefo.api.util.get_image')
-@patch('synnefo.logic.rapi_pool.GanetiRapiClient')
-class ServerActionAPITest(ComputeAPITest):
-    def test_actions(self, mrapi, mimage):
-        actions = ['start', 'shutdown', 'reboot']
-        vm = mfactory.VirtualMachineFactory()
-        vm.operstate = "STOPPED"
-        vm.save()
-        mrapi().StartupInstance.return_value = 0
-        mrapi().ShutdownInstance.return_value = 1
-        mrapi().RebootInstance.return_value = 2
-        for jobId, action in enumerate(actions):
-            if action in ["shutdown", "reboot"]:
-                vm.operstate = "STARTED"
-            else:
-                vm.operstate = "STOPPED"
-            vm.task = None
-            vm.task_job_id = None
-            vm.save()
-            val = {'type': 'HARD'} if action == 'reboot' else {}
-            request = {action: val}
-            response = self.mypost('servers/%d/action' % vm.id,
-                                   vm.userid, json.dumps(request), 'json')
-            self.assertEqual(response.status_code, 202)
-            if action == 'shutdown':
-                self.assertEqual(VirtualMachine.objects.get(id=vm.id).task,
-                                 "STOP")
-            else:
-                self.assertEqual(VirtualMachine.objects.get(id=vm.id).task,
-                                 action.upper())
-            self.assertEqual(VirtualMachine.objects.get(id=vm.id).task_job_id,
-                             jobId)
-
-    def test_action_in_building_vm(self, mrapi, mimage):
-        """Test building in progress"""
-        vm = mfactory.VirtualMachineFactory(operstate="BUILD")
-        request = {'start': {}}
-        with mocked_quotaholder():
-            response = self.mypost('servers/%d/action' % vm.id,
-                                   vm.userid, json.dumps(request), 'json')
-        self.assertEqual(response.status_code, 409)
-        self.assertFalse(mrapi.mock_calls)
-
-    def test_destroy_build_vm(self, mrapi, mimage):
-        """Test building in progress"""
-        vm = mfactory.VirtualMachineFactory()
-        mrapi().DeleteInstance.return_value = 2
-        response = self.mydelete('servers/%d' % vm.id,
-                                 vm.userid)
-        self.assertSuccess(response)
-        mrapi().RemoveInstance.assert_called_once()
-
-    def test_firewall(self, mrapi, mimage):
-        vm = mfactory.VirtualMachineFactory()
-        vm.operstate = "STOPPED"
-        vm.save()
-        request = {'firewallProfile': {'profile': 'PROTECTED'}}
-        response = self.mypost('servers/%d/action' % vm.id,
-                               vm.userid, json.dumps(request), 'json')
-        self.assertEqual(response.status_code, 202)
-        mrapi().ModifyInstance.assert_called_once()
-
-    def test_unsupported_firewall(self, mrapi, mimage):
-        vm = mfactory.VirtualMachineFactory()
-        vm.operstate = "STOPPED"
-        vm.save()
-        request = {'firewallProfile': {'profile': 'FOO'}}
-        response = self.mypost('servers/%d/action' % vm.id,
-                               vm.userid, json.dumps(request), 'json')
-        self.assertBadRequest(response)
-        self.assertFalse(mrapi.mock_calls)
-
-    def test_resize_vm(self, mrapi, mimage):
-        flavor = mfactory.FlavorFactory(cpu=1, ram=1024)
-        # Check building VM
-        vm = self.get_vm(flavor=flavor, operstate="BUILD")
-        request = {'resize': {'flavorRef': flavor.id}}
-        response = self.mypost('servers/%d/action' % vm.id,
-                             vm.userid, json.dumps(request), 'json')
-        self.assertFault(response, 409, "buildInProgress")
-        # Check same Flavor
-        vm = self.get_vm(flavor=flavor, operstate="STOPPED")
-        request = {'resize': {'flavorRef': flavor.id}}
-        response = self.mypost('servers/%d/action' % vm.id,
-                             vm.userid, json.dumps(request), 'json')
-        self.assertBadRequest(response)
-        # Check flavor with different disk
-        flavor2 = mfactory.FlavorFactory(disk=1024)
-        flavor3 = mfactory.FlavorFactory(disk=2048)
-        vm = self.get_vm(flavor=flavor2, operstate="STOPPED")
-        request = {'resize': {'flavorRef': flavor3.id}}
-        response = self.mypost('servers/%d/action' % vm.id,
-                             vm.userid, json.dumps(request), 'json')
-        self.assertBadRequest(response)
-        flavor2 = mfactory.FlavorFactory(disk_template="foo")
-        flavor3 = mfactory.FlavorFactory(disk_template="baz")
-        vm = self.get_vm(flavor=flavor2, operstate="STOPPED")
-        request = {'resize': {'flavorRef': flavor3.id}}
-        response = self.mypost('servers/%d/action' % vm.id,
-                             vm.userid, json.dumps(request), 'json')
-        self.assertBadRequest(response)
-        # Check success
-        vm = self.get_vm(flavor=flavor, operstate="STOPPED")
-        flavor4 = mfactory.FlavorFactory(disk_template=flavor.disk_template,
-                                         disk=flavor.disk,
-                                         cpu=4, ram=2048)
-        request = {'resize': {'flavorRef': flavor4.id}}
-        mrapi().ModifyInstance.return_value = 42
-        response = self.mypost('servers/%d/action' % vm.id,
-                             vm.userid, json.dumps(request), 'json')
-        self.assertEqual(response.status_code, 202)
-        vm = VirtualMachine.objects.get(id=vm.id)
-        self.assertEqual(vm.task_job_id, 42)
-        name, args, kwargs = mrapi().ModifyInstance.mock_calls[0]
-        self.assertEqual(kwargs["beparams"]["vcpus"], 4)
-        self.assertEqual(kwargs["beparams"]["minmem"], 2048)
-        self.assertEqual(kwargs["beparams"]["maxmem"], 2048)
-
-    def test_action_on_resizing_vm(self, mrapi, mimage):
-        vm = mfactory.VirtualMachineFactory()
-        vm.operstate = "RESIZE"
-        vm.save()
-        for action in VirtualMachine.ACTIONS:
-            request = {action[0]: ""}
-            response = self.mypost('servers/%d/action' % vm.id,
-                                 vm.userid, json.dumps(request), 'json')
-            self.assertBadRequest(response)
-        # however you can destroy
-        mrapi().DeleteInstance.return_value = 42
-        response = self.mydelete('servers/%d' % vm.id,
-                                 vm.userid)
-        self.assertSuccess(response)
-
-    def get_vm(self, flavor, operstate):
-        vm = mfactory.VirtualMachineFactory(flavor=flavor)
-        vm.operstate = operstate
-        vm.backendjobstatus = "success"
-        vm.save()
-        return vm
-
-
-class ServerVNCConsole(ComputeAPITest):
-    def test_not_active_server(self):
-        """Test console req for not ACTIVE server returns badRequest"""
-        vm = mfactory.VirtualMachineFactory(operstate="BUILD")
-        data = json.dumps({'console': {'type': 'vnc'}})
-        response = self.mypost('servers/%d/action' % vm.id,
-                               vm.userid, data, 'json')
-        self.assertBadRequest(response)
-
-    def test_active_server(self):
-        """Test console req for ACTIVE server"""
-        vm = mfactory.VirtualMachineFactory()
-        vm.operstate = 'STARTED'
-        vm.save()
-
-        data = json.dumps({'console': {'type': 'vnc'}})
-        with override_settings(settings, TEST=True):
-            response = self.mypost('servers/%d/action' % vm.id,
-                                   vm.userid, data, 'json')
-        self.assertEqual(response.status_code, 200)
-        reply = json.loads(response.content)
-        self.assertEqual(reply.keys(), ['console'])
-        console = reply['console']
-        self.assertEqual(console['type'], 'vnc')
-        self.assertEqual(set(console.keys()),
-                         set(['type', 'host', 'port', 'password']))
-
-    def test_wrong_console_type(self):
-        """Test console req for ACTIVE server"""
-        vm = mfactory.VirtualMachineFactory()
-        vm.operstate = 'STARTED'
-        vm.save()
-
-        data = json.dumps({'console': {'type': 'foo'}})
-        response = self.mypost('servers/%d/action' % vm.id,
-                               vm.userid, data, 'json')
-        self.assertBadRequest(response)
diff --git a/snf-cyclades-app/synnefo/api/test/versions.py b/snf-cyclades-app/synnefo/api/test/versions.py
deleted file mode 100644
index ed06f96..0000000
--- a/snf-cyclades-app/synnefo/api/test/versions.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright 2012-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 django.utils import simplejson as json
-from django.test import TestCase
-from snf_django.utils.testing import astakos_user
-from synnefo.cyclades_settings import cyclades_services
-from synnefo.lib.services import get_service_path
-from synnefo.lib import join_urls
-
-
-class APITest(TestCase):
-    def test_api_version(self):
-        """Check API version."""
-        path = get_service_path(cyclades_services,
-                                'compute', version='v2.0')
-        with astakos_user('user'):
-            response = self.client.get(path)
-        self.assertEqual(response.status_code, 200)
-        api_version = json.loads(response.content)['version']
-        self.assertEqual(api_version['id'], 'v2.0')
-        self.assertEqual(api_version['status'], 'CURRENT')
-
-    def test_catch_wrong_api_paths(self, *args):
-        path = get_service_path(cyclades_services,
-                                'compute', version='v2.0')
-        response = self.client.get(join_urls(path, 'nonexistent'))
-        self.assertEqual(response.status_code, 400)
-        try:
-            error = json.loads(response.content)
-        except ValueError:
-            self.assertTrue(False)
diff --git a/snf-cyclades-app/synnefo/api/tests.py b/snf-cyclades-app/synnefo/api/tests.py
deleted file mode 100644
index c958245..0000000
--- a/snf-cyclades-app/synnefo/api/tests.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2012 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.
-
-# Import TestCases
-from synnefo.api.test.servers import *
-from synnefo.api.test.networks import *
-from synnefo.api.test.flavors import *
-from synnefo.api.test.images import *
-from synnefo.api.test.versions import *
-from synnefo.api.test.extensions import *
-from synnefo.api.test.floating_ips import *
diff --git a/snf-cyclades-app/synnefo/api/tests/__init__.py b/snf-cyclades-app/synnefo/api/tests/__init__.py
new file mode 100644
index 0000000..071c3e6
--- /dev/null
+++ b/snf-cyclades-app/synnefo/api/tests/__init__.py
@@ -0,0 +1,41 @@
+# Copyright 2012 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.
+
+# Import TestCases
+from .servers import *
+from .networks import *
+from .flavors import *
+from .images import *
+from .versions import *
+from .extensions import *
+from .floating_ips import *
diff --git a/snf-cyclades-app/synnefo/api/tests/extensions.py b/snf-cyclades-app/synnefo/api/tests/extensions.py
new file mode 100644
index 0000000..180ea57
--- /dev/null
+++ b/snf-cyclades-app/synnefo/api/tests/extensions.py
@@ -0,0 +1,59 @@
+# 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.
+
+import json
+
+from snf_django.utils.testing import BaseAPITest
+from synnefo.lib.services import get_service_path
+from synnefo.cyclades_settings import cyclades_services
+from synnefo.lib import join_urls
+
+COMPUTE_URL = get_service_path(cyclades_services, 'compute',
+                               version='v2.0')
+EXTENSIONS_URL = join_urls(COMPUTE_URL, "extensions/")
+
+
+class ExtensionsAPITest(BaseAPITest):
+    def test_list(self):
+        response = self.get(EXTENSIONS_URL, "user")
+        self.assertSuccess(response)
+        extensions = json.loads(response.content)["extensions"]
+        self.assertEqual(extensions, [])
+
+    def test_get(self):
+        response = self.get(join_urls(EXTENSIONS_URL, "SNF"), "user")
+        self.assertEqual(response.status_code, 404)
+        response = self.get(join_urls(EXTENSIONS_URL, "SNF_asfas_da"), "user")
+        self.assertEqual(response.status_code, 404)
+        response = self.get(join_urls(EXTENSIONS_URL, "SNF-AD"), "user")
+        self.assertEqual(response.status_code, 404)
diff --git a/snf-cyclades-app/synnefo/api/tests/flavors.py b/snf-cyclades-app/synnefo/api/tests/flavors.py
new file mode 100644
index 0000000..bc97987
--- /dev/null
+++ b/snf-cyclades-app/synnefo/api/tests/flavors.py
@@ -0,0 +1,146 @@
+# Copyright 2012 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.
+
+import json
+
+from snf_django.utils.testing import BaseAPITest
+from synnefo.db.models import Flavor
+from synnefo.db.models_factory import FlavorFactory
+from synnefo.lib.services import get_service_path
+from synnefo.cyclades_settings import cyclades_services
+from synnefo.lib import join_urls
+
+
+class FlavorAPITest(BaseAPITest):
+
+    def setUp(self):
+        self.flavor1 = FlavorFactory()
+        self.flavor2 = FlavorFactory(deleted=True)
+        self.flavor3 = FlavorFactory()
+        self.compute_path = get_service_path(cyclades_services, 'compute',
+                                             version='v2.0')
+
+
+    def myget(self, path):
+        path = join_urls(self.compute_path, path)
+        return self.get(path)
+
+
+    def test_flavor_list(self):
+        """Test if the expected list of flavors is returned."""
+        response = self.myget('flavors')
+        self.assertSuccess(response)
+
+        api_flavors = json.loads(response.content)['flavors']
+        db_flavors = Flavor.objects.filter(deleted=False)
+        self.assertEqual(len(api_flavors), len(db_flavors))
+        for api_flavor in api_flavors:
+            db_flavor = Flavor.objects.get(id=api_flavor['id'])
+            self.assertEqual(api_flavor['id'], db_flavor.id)
+            self.assertEqual(api_flavor['name'], db_flavor.name)
+
+    def test_flavors_details(self):
+        """Test if the flavors details are returned."""
+        response = self.myget('flavors/detail')
+        self.assertSuccess(response)
+
+        db_flavors = Flavor.objects.filter(deleted=False)
+        api_flavors = json.loads(response.content)['flavors']
+
+        self.assertEqual(len(db_flavors), len(api_flavors))
+
+        for i in range(0, len(db_flavors)):
+            api_flavor = api_flavors[i]
+            db_flavor = Flavor.objects.get(id=db_flavors[i].id)
+            self.assertEqual(api_flavor['vcpus'], db_flavor.cpu)
+            self.assertEqual(api_flavor['id'], db_flavor.id)
+            self.assertEqual(api_flavor['disk'], db_flavor.disk)
+            self.assertEqual(api_flavor['name'], db_flavor.name)
+            self.assertEqual(api_flavor['ram'], db_flavor.ram)
+            self.assertEqual(api_flavor['SNF:disk_template'],
+                                        db_flavor.disk_template)
+
+    def test_flavor_details(self):
+        """Test if the expected flavor is returned."""
+        flavor = self.flavor3
+
+        response = self.myget('flavors/%d' % flavor.id)
+        self.assertSuccess(response)
+
+        api_flavor = json.loads(response.content)['flavor']
+        db_flavor = Flavor.objects.get(id=flavor.id)
+        self.assertEqual(api_flavor['vcpus'], db_flavor.cpu)
+        self.assertEqual(api_flavor['id'], db_flavor.id)
+        self.assertEqual(api_flavor['disk'], db_flavor.disk)
+        self.assertEqual(api_flavor['name'], db_flavor.name)
+        self.assertEqual(api_flavor['ram'], db_flavor.ram)
+        self.assertEqual(api_flavor['SNF:disk_template'],
+                         db_flavor.disk_template)
+
+    def test_deleted_flavor_details(self):
+        """Test that API returns details for deleted flavors"""
+        flavor = self.flavor2
+        response = self.myget('flavors/%d' % flavor.id)
+        self.assertSuccess(response)
+        api_flavor = json.loads(response.content)['flavor']
+        self.assertEquals(api_flavor['name'], flavor.name)
+
+    def test_deleted_flavors_list(self):
+        """Test that deleted flavors do not appear to flavors list"""
+        response = self.myget('flavors')
+        self.assertSuccess(response)
+        api_flavors = json.loads(response.content)['flavors']
+        self.assertEqual(len(api_flavors), 2)
+
+    def test_deleted_flavors_details(self):
+        """Test that deleted flavors do not appear to flavors detail list"""
+        FlavorFactory(deleted=True)
+        response = self.myget('flavors/detail')
+        self.assertSuccess(response)
+        api_flavors = json.loads(response.content)['flavors']
+        self.assertEqual(len(api_flavors), 2)
+
+    def test_wrong_flavor(self):
+        """Test 404 result when requesting a flavor that does not exist."""
+
+        # XXX: flavors/22 below fails for no apparent reason
+        response = self.myget('flavors/%d' % 23)
+        self.assertItemNotFound(response)
+
+    def test_catch_wrong_api_paths(self, *args):
+        response = self.myget('nonexistent')
+        self.assertEqual(response.status_code, 400)
+        try:
+            error = json.loads(response.content)
+        except ValueError:
+            self.assertTrue(False)
diff --git a/snf-cyclades-app/synnefo/api/tests/floating_ips.py b/snf-cyclades-app/synnefo/api/tests/floating_ips.py
new file mode 100644
index 0000000..8f6880f
--- /dev/null
+++ b/snf-cyclades-app/synnefo/api/tests/floating_ips.py
@@ -0,0 +1,334 @@
+# Copyright 2012 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.
+
+import json
+
+from snf_django.utils.testing import BaseAPITest, mocked_quotaholder
+from synnefo.db.models import FloatingIP
+from synnefo.db.models_factory import (FloatingIPFactory, NetworkFactory,
+                                       VirtualMachineFactory,
+                                       NetworkInterfaceFactory,
+                                       BackendNetworkFactory)
+from mock import patch, Mock
+from functools import partial
+
+from synnefo.cyclades_settings import cyclades_services
+from synnefo.lib.services import get_service_path
+from synnefo.lib import join_urls
+
+
+compute_path = get_service_path(cyclades_services, "compute", version="v2.0")
+URL = join_urls(compute_path, "os-floating-ips")
+NETWORKS_URL = join_urls(compute_path, "networks")
+SERVERS_URL = join_urls(compute_path, "servers")
+
+FloatingIPPoolFactory = partial(NetworkFactory, public=True, deleted=False,
+                                floating_ip_pool=True)
+
+
+class FloatingIPAPITest(BaseAPITest):
+    def test_no_floating_ip(self):
+        response = self.get(URL)
+        self.assertSuccess(response)
+        self.assertEqual(json.loads(response.content)["floating_ips"], [])
+
+    def test_list_ips(self):
+        ip = FloatingIPFactory(userid="user1")
+        FloatingIPFactory(userid="user1", deleted=True)
+        with mocked_quotaholder():
+            response = self.get(URL, "user1")
+        self.assertSuccess(response)
+        api_ip = json.loads(response.content)["floating_ips"][0]
+        self.assertEqual(api_ip,
+                         {"instance_id": str(ip.machine.id), "ip": ip.ipv4,
+                          "fixed_ip": None, "id": str(ip.id),  "pool":
+                          str(ip.network.id)})
+
+    def test_get_ip(self):
+        ip = FloatingIPFactory(userid="user1")
+        with mocked_quotaholder():
+            response = self.get(URL + "/%s" % ip.id, "user1")
+        self.assertSuccess(response)
+        api_ip = json.loads(response.content)["floating_ip"]
+        self.assertEqual(api_ip,
+                         {"instance_id": str(ip.machine.id), "ip": ip.ipv4,
+                          "fixed_ip": None, "id": str(ip.id),  "pool":
+                          str(ip.network.id)})
+
+    def test_wrong_user(self):
+        ip = FloatingIPFactory(userid="user1")
+        with mocked_quotaholder():
+            response = self.delete(URL + "/%s" % ip.id, "user2")
+        self.assertItemNotFound(response)
+
+    def test_deleted_ip(self):
+        ip = FloatingIPFactory(userid="user1", deleted=True)
+        with mocked_quotaholder():
+            response = self.delete(URL + "/%s" % ip.id, "user1")
+        self.assertItemNotFound(response)
+
+    def test_reserve(self):
+        net = FloatingIPPoolFactory(userid="test_user",
+                                    subnet="192.168.2.0/24",
+                                    gateway=None)
+        request = {'pool': net.id}
+        with mocked_quotaholder():
+            response = self.post(URL, "test_user", json.dumps(request), "json")
+        self.assertSuccess(response)
+        ip = FloatingIP.objects.get()
+        self.assertEqual(ip.ipv4, "192.168.2.1")
+        self.assertEqual(ip.machine, None)
+        self.assertEqual(ip.network, net)
+        self.assertEqual(json.loads(response.content)["floating_ip"],
+                         {"instance_id": None, "ip": "192.168.2.1",
+                          "fixed_ip": None, "id": "1", "pool": "1"})
+
+    def test_reserve_no_pool(self):
+        # No networks
+        with mocked_quotaholder():
+            response = self.post(URL, "test_user", json.dumps({}), "json")
+        self.assertFault(response, 413, "overLimit")
+        # Full network
+        FloatingIPPoolFactory(userid="test_user",
+                              subnet="192.168.2.0/32",
+                              gateway=None)
+        with mocked_quotaholder():
+            response = self.post(URL, "test_user", json.dumps({}), "json")
+        self.assertFault(response, 413, "overLimit")
+        # Success
+        net2 = FloatingIPPoolFactory(userid="test_user",
+                                     subnet="192.168.2.0/24",
+                                     gateway=None)
+        with mocked_quotaholder():
+            response = self.post(URL, "test_user", json.dumps({}), "json")
+        self.assertSuccess(response)
+        self.assertEqual(json.loads(response.content)["floating_ip"],
+                         {"instance_id": None, "ip": "192.168.2.1",
+                          "fixed_ip": None, "id": "1", "pool": str(net2.id)})
+
+    def test_reserve_full(self):
+        net = FloatingIPPoolFactory(userid="test_user",
+                                    subnet="192.168.2.0/32")
+        request = {'pool': net.id}
+        with mocked_quotaholder():
+            response = self.post(URL, "test_user", json.dumps(request), "json")
+        self.assertEqual(response.status_code, 413)
+
+    def test_reserve_with_address(self):
+        net = FloatingIPPoolFactory(userid="test_user",
+                                    subnet="192.168.2.0/24")
+        request = {'pool': net.id, "address": "192.168.2.10"}
+        with mocked_quotaholder():
+            response = self.post(URL, "test_user", json.dumps(request), "json")
+        self.assertSuccess(response)
+        self.assertEqual(json.loads(response.content)["floating_ip"],
+                         {"instance_id": None, "ip": "192.168.2.10",
+                          "fixed_ip": None, "id": "1", "pool": "1"})
+
+        # Already reserved
+        FloatingIPFactory(network=net, ipv4="192.168.2.3")
+        request = {'pool': net.id, "address": "192.168.2.3"}
+        with mocked_quotaholder():
+            response = self.post(URL, "test_user", json.dumps(request), "json")
+        self.assertFault(response, 409, "conflict")
+
+        # Already used
+        pool = net.get_pool()
+        pool.reserve("192.168.2.5")
+        pool.save()
+        # ..by another_user
+        nic = NetworkInterfaceFactory(network=net, ipv4="192.168.2.5",
+                                      machine__userid="test2")
+        request = {'pool': net.id, "address": "192.168.2.5"}
+        with mocked_quotaholder():
+            response = self.post(URL, "test_user", json.dumps(request), "json")
+        self.assertFault(response, 409, "conflict")
+        # ..and by him
+        nic.delete()
+        NetworkInterfaceFactory(network=net, ipv4="192.168.2.5",
+                                machine__userid="test_user")
+        request = {'pool': net.id, "address": "192.168.2.5"}
+        with mocked_quotaholder():
+            response = self.post(URL, "test_user", json.dumps(request), "json")
+        self.assertSuccess(response)
+
+        # Address out of pool
+        request = {'pool': net.id, "address": "192.168.3.5"}
+        with mocked_quotaholder():
+            response = self.post(URL, "test_user", json.dumps(request), "json")
+        self.assertBadRequest(response)
+
+    def test_release_in_use(self):
+        ip = FloatingIPFactory()
+        vm = ip.machine
+        vm.operstate = "ACTIVE"
+        vm.userid = ip.userid
+        vm.save()
+        vm.nics.create(index=0, ipv4=ip.ipv4, network=ip.network,
+                       state="ACTIVE")
+        with mocked_quotaholder():
+            response = self.delete(URL + "/%s" % ip.id, ip.userid)
+        self.assertFault(response, 409, "conflict")
+        # Also send a notification to remove the NIC and assert that FIP is in
+        # use until notification from ganeti arrives
+        request = {"removeFloatingIp": {"address": ip.ipv4}}
+        url = SERVERS_URL + "/%s/action" % vm.id
+        with patch('synnefo.logic.rapi_pool.GanetiRapiClient') as c:
+            c().ModifyInstance.return_value = 10
+            response = self.post(url, vm.userid, json.dumps(request),
+                                 "json")
+        self.assertEqual(response.status_code, 202)
+        with mocked_quotaholder():
+            response = self.delete(URL + "/%s" % ip.id, ip.userid)
+        self.assertFault(response, 409, "conflict")
+
+    def test_release(self):
+        ip = FloatingIPFactory(machine=None)
+        with mocked_quotaholder():
+            response = self.delete(URL + "/%s" % ip.id, ip.userid)
+        self.assertSuccess(response)
+        ips_after = FloatingIP.objects.filter(id=ip.id)
+        self.assertEqual(len(ips_after), 0)
+
+    @patch("synnefo.logic.backend", Mock())
+    def test_delete_network_with_floating_ips(self):
+        ip = FloatingIPFactory(machine=None, network__flavor="IP_LESS_ROUTED")
+        net = ip.network
+        # Can not remove network with floating IPs
+        with mocked_quotaholder():
+            response = self.delete(NETWORKS_URL + "/%s" % net.id,
+                                   net.userid)
+        self.assertFault(response, 421, "networkInUse")
+        # But we can with only deleted Floating Ips
+        ip.deleted = True
+        ip.save()
+        with mocked_quotaholder():
+            response = self.delete(NETWORKS_URL + "/%s" % net.id,
+                                   net.userid)
+        self.assertSuccess(response)
+
+
+POOLS_URL = join_urls(compute_path, "os-floating-ip-pools")
+
+
+class FloatingIPPoolsAPITest(BaseAPITest):
+    def test_no_pool(self):
+        response = self.get(POOLS_URL)
+        self.assertSuccess(response)
+        self.assertEqual(json.loads(response.content)["floating_ip_pools"], [])
+
+    def test_list_pools(self):
+        net = FloatingIPPoolFactory(subnet="192.168.0.0/30",
+                                    gateway="192.168.0.1")
+        NetworkFactory(public=True, deleted=True)
+        NetworkFactory(public=False, deleted=False)
+        NetworkFactory(public=True, deleted=False)
+        response = self.get(POOLS_URL)
+        self.assertSuccess(response)
+        self.assertEqual(json.loads(response.content)["floating_ip_pools"],
+                         [{"name": str(net.id), "size": 4, "free": 1}])
+
+
+class FloatingIPActionsTest(BaseAPITest):
+    def setUp(self):
+        vm = VirtualMachineFactory()
+        vm.operstate = "ACTIVE"
+        vm.save()
+        self.vm = vm
+
+    def test_bad_request(self):
+        url = SERVERS_URL + "/%s/action" % self.vm.id
+        response = self.post(url, self.vm.userid, json.dumps({}), "json")
+        self.assertBadRequest(response)
+        response = self.post(url, self.vm.userid,
+                             json.dumps({"addFloatingIp": {}}),
+                             "json")
+        self.assertBadRequest(response)
+
+    @patch('synnefo.logic.rapi_pool.GanetiRapiClient')
+    def test_add_floating_ip(self, mock):
+        # Not exists
+        url = SERVERS_URL + "/%s/action" % self.vm.id
+        request = {"addFloatingIp": {"address": "10.0.0.1"}}
+        response = self.post(url, self.vm.userid, json.dumps(request), "json")
+        self.assertItemNotFound(response)
+        # In use
+        vm1 = VirtualMachineFactory()
+        ip1 = FloatingIPFactory(userid=self.vm.userid, machine=vm1)
+        BackendNetworkFactory(network=ip1.network, backend=vm1.backend,
+                              operstate='ACTIVE')
+        request = {"addFloatingIp": {"address": ip1.ipv4}}
+        response = self.post(url, self.vm.userid, json.dumps(request), "json")
+        self.assertFault(response, 409, "conflict")
+        # Success
+        ip1 = FloatingIPFactory(userid=self.vm.userid, machine=None)
+        BackendNetworkFactory(network=ip1.network, backend=self.vm.backend,
+                              operstate='ACTIVE')
+        request = {"addFloatingIp": {"address": ip1.ipv4}}
+        mock().ModifyInstance.return_value = 1
+        response = self.post(url, self.vm.userid, json.dumps(request), "json")
+        self.assertEqual(response.status_code, 202)
+        ip1_after = FloatingIP.objects.get(id=ip1.id)
+        self.assertEqual(ip1_after.machine, self.vm)
+        self.assertTrue(ip1_after.in_use())
+        self.vm.nics.create(ipv4=ip1_after.ipv4, network=ip1_after.network,
+                            state="ACTIVE", index=0)
+        response = self.get(SERVERS_URL + "/%s" % self.vm.id,
+                            self.vm.userid)
+        self.assertSuccess(response)
+        nic = json.loads(response.content)["server"]["attachments"][0]
+        self.assertEqual(nic["OS-EXT-IPS:type"], "floating")
+
+    @patch('synnefo.logic.rapi_pool.GanetiRapiClient')
+    def test_remove_floating_ip(self, mock):
+        # Not exists
+        url = SERVERS_URL + "/%s/action" % self.vm.id
+        request = {"removeFloatingIp": {"address": "10.0.0.1"}}
+        response = self.post(url, self.vm.userid, json.dumps(request), "json")
+        self.assertItemNotFound(response)
+        # Not In Use
+        ip1 = FloatingIPFactory(userid=self.vm.userid, machine=None)
+        request = {"removeFloatingIp": {"address": ip1.ipv4}}
+        response = self.post(url, self.vm.userid, json.dumps(request), "json")
+        self.assertItemNotFound(response)
+        # Success
+        ip1 = FloatingIPFactory(userid=self.vm.userid, machine=self.vm)
+        NetworkInterfaceFactory(machine=self.vm, ipv4=ip1.ipv4)
+        request = {"removeFloatingIp": {"address": ip1.ipv4}}
+        mock().ModifyInstance.return_value = 2
+        response = self.post(url, self.vm.userid, json.dumps(request), "json")
+        self.assertEqual(response.status_code, 202)
+        # Yet used. Wait for the callbacks
+        ip1_after = FloatingIP.objects.get(id=ip1.id)
+        self.assertEqual(ip1_after.machine, self.vm)
+        self.assertTrue(ip1_after.in_use())
diff --git a/snf-cyclades-app/synnefo/api/tests/images.py b/snf-cyclades-app/synnefo/api/tests/images.py
new file mode 100644
index 0000000..ff844d7
--- /dev/null
+++ b/snf-cyclades-app/synnefo/api/tests/images.py
@@ -0,0 +1,384 @@
+# Copyright 2012 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.
+
+import json
+
+from snf_django.lib.api import faults
+from snf_django.utils.testing import BaseAPITest
+from synnefo.lib.services import get_service_path
+from synnefo.cyclades_settings import cyclades_services
+from synnefo.lib import join_urls
+
+from mock import patch
+from functools import wraps
+
+
+def assert_backend_closed(func):
+    """Decorator for ensuring that ImageBackend is returned to pool."""
+    @wraps(func)
+    def wrapper(self, backend):
+        result = func(self, backend)
+        if backend.called is True:
+            backend.return_value.close.asssert_called
+        return result
+    return wrapper
+
+
+class ComputeAPITest(BaseAPITest):
+    def setUp(self, *args, **kwargs):
+        super(ComputeAPITest, self).setUp(*args, **kwargs)
+        self.compute_path = get_service_path(cyclades_services, 'compute',
+                                             version='v2.0')
+    def myget(self, path, *args, **kwargs):
+        path = join_urls(self.compute_path, path)
+        return self.get(path, *args, **kwargs)
+
+    def myput(self, path, *args, **kwargs):
+        path = join_urls(self.compute_path, path)
+        return self.put(path, *args, **kwargs)
+
+    def mypost(self, path, *args, **kwargs):
+        path = join_urls(self.compute_path, path)
+        return self.post(path, *args, **kwargs)
+
+    def mydelete(self, path, *args, **kwargs):
+        path = join_urls(self.compute_path, path)
+        return self.delete(path, *args, **kwargs)
+
+
+@patch('synnefo.plankton.backend.ImageBackend')
+class ImageAPITest(ComputeAPITest):
+    @assert_backend_closed
+    def test_create_image(self, mimage):
+        """Test that create image is not implemented"""
+        response = self.mypost('images/', 'user', json.dumps(''), 'json')
+        self.assertEqual(response.status_code, 501)
+
+    @assert_backend_closed
+    def test_list_images(self, mimage):
+        """Test that expected list of images is returned"""
+        images = [{'id': 1, 'name': 'image-1'},
+                  {'id': 2, 'name': 'image-2'},
+                  {'id': 3, 'name': 'image-3'}]
+        mimage().list_images.return_value = images
+        response = self.myget('images', 'user')
+        self.assertSuccess(response)
+        api_images = json.loads(response.content)['images']
+        self.assertEqual(images, api_images)
+
+    @assert_backend_closed
+    def test_list_images_detail(self, mimage):
+        images = [{'id': 1,
+                   'name': 'image-1',
+                   'status':'available',
+                   'created_at': '2012-11-26 11:52:54',
+                   'updated_at': '2012-12-26 11:52:54',
+                   'owner': 'user1',
+                   'deleted_at': '',
+                   'properties': {'foo':'bar'}},
+                  {'id': 2,
+                   'name': 'image-2',
+                   'status': 'deleted',
+                   'created_at': '2012-11-26 11:52:54',
+                   'updated_at': '2012-12-26 11:52:54',
+                   'owner': 'user1',
+                   'deleted_at': '2012-12-27 11:52:54',
+                   'properties': ''},
+                  {'id': 3,
+                   'name': 'image-3',
+                   'status': 'available',
+                   'created_at': '2012-11-26 11:52:54',
+                   'deleted_at': '',
+                   'updated_at': '2012-12-26 11:52:54',
+                   'owner': 'user1',
+                   'properties': ''}]
+        result_images = [
+                  {'id': 1,
+                   'name': 'image-1',
+                   'status':'ACTIVE',
+                   'progress': 100,
+                   'created': '2012-11-26T11:52:54+00:00',
+                   'updated': '2012-12-26T11:52:54+00:00',
+                   'user_id': 'user1',
+                   'tenant_id': 'user1',
+                   'metadata': {'foo':'bar'}},
+                  {'id': 2,
+                   'name': 'image-2',
+                   'status': 'DELETED',
+                   'progress': 0,
+                   'user_id': 'user1',
+                   'tenant_id': 'user1',
+                   'created': '2012-11-26T11:52:54+00:00',
+                   'updated': '2012-12-26T11:52:54+00:00',
+                   'metadata': {}},
+                  {'id': 3,
+                   'name': 'image-3',
+                   'status': 'ACTIVE',
+                   'progress': 100,
+                   'user_id': 'user1',
+                   'tenant_id': 'user1',
+                   'created': '2012-11-26T11:52:54+00:00',
+                   'updated': '2012-12-26T11:52:54+00:00',
+                   'metadata': {}}]
+        mimage().list_images.return_value = images
+        response = self.myget('images/detail', 'user')
+        self.assertSuccess(response)
+        api_images = json.loads(response.content)['images']
+        self.assertEqual(len(result_images), len(api_images))
+        map(lambda image: image.pop("links"), api_images)
+        self.assertEqual(result_images, api_images)
+
+    @assert_backend_closed
+    def test_list_images_detail_since(self, mimage):
+        from datetime import datetime, timedelta
+        from time import sleep
+        old_time = datetime.now()
+        new_time = old_time + timedelta(seconds=0.1)
+        sleep(0.1)
+        images = [
+                  {'id': 1,
+                   'name': 'image-1',
+                   'status':'available',
+                   'progress': 100,
+                   'created_at': old_time.isoformat(),
+                   'deleted_at': '',
+                   'updated_at': old_time.isoformat(),
+                   'owner': 'user1',
+                   'properties': ''},
+                  {'id': 2,
+                   'name': 'image-2',
+                   'status': 'deleted',
+                   'progress': 0,
+                   'owner': 'user2',
+                   'created_at': new_time.isoformat(),
+                   'updated_at': new_time.isoformat(),
+                   'deleted_at': new_time.isoformat(),
+                   'properties': ''}]
+        mimage().list_images.return_value = images
+        response =\
+            self.myget('images/detail?changes-since=%sUTC' % new_time)
+        self.assertSuccess(response)
+        api_images = json.loads(response.content)['images']
+        self.assertEqual(1, len(api_images))
+
+    @assert_backend_closed
+    def test_get_image_details(self, mimage):
+        image = {'id': 42,
+                 'name': 'image-1',
+                 'status': 'available',
+                 'created_at': '2012-11-26 11:52:54',
+                 'updated_at': '2012-12-26 11:52:54',
+                 'deleted_at': '',
+                 'owner': 'user1',
+                 'properties': {'foo': 'bar'}}
+        result_image = \
+                  {'id': 42,
+                   'name': 'image-1',
+                   'status': 'ACTIVE',
+                   'progress': 100,
+                   'created': '2012-11-26T11:52:54+00:00',
+                   'updated': '2012-12-26T11:52:54+00:00',
+                   'user_id': 'user1',
+                   'tenant_id': 'user1',
+                   'metadata': {'foo': 'bar'}}
+        mimage.return_value.get_image.return_value = image
+        response = self.myget('images/42', 'user')
+        self.assertSuccess(response)
+        api_image = json.loads(response.content)['image']
+        api_image.pop("links")
+        self.assertEqual(api_image, result_image)
+
+    @assert_backend_closed
+    def test_invalid_image(self, mimage):
+        mimage.return_value.get_image.side_effect = faults.ItemNotFound('Image not found')
+        response = self.myget('images/42', 'user')
+        self.assertItemNotFound(response)
+
+    @assert_backend_closed
+    def test_delete_image(self, mimage):
+        response = self.mydelete("images/42", "user")
+        self.assertEqual(response.status_code, 204)
+        mimage.return_value.unregister.assert_called_once_with('42')
+        mimage.return_value._delete.assert_not_called('42')
+
+    @assert_backend_closed
+    def test_catch_wrong_api_paths(self, *args):
+        response = self.myget('nonexistent')
+        self.assertEqual(response.status_code, 400)
+        try:
+            error = json.loads(response.content)
+        except ValueError:
+            self.assertTrue(False)
+
+    @assert_backend_closed
+    def test_method_not_allowed(self, *args):
+        # /images/ allows only POST, GET
+        response = self.myput('images', '', '')
+        self.assertMethodNotAllowed(response)
+        response = self.mydelete('images')
+        self.assertMethodNotAllowed(response)
+
+        # /images/<imgid>/ allows only GET, DELETE
+        response = self.mypost("images/42")
+        self.assertMethodNotAllowed(response)
+        response = self.myput('images/42', '', '')
+        self.assertMethodNotAllowed(response)
+
+        # /images/<imgid>/metadata/ allows only POST, GET
+        response = self.myput('images/42/metadata', '', '')
+        self.assertMethodNotAllowed(response)
+        response = self.mydelete('images/42/metadata')
+        self.assertMethodNotAllowed(response)
+
+        # /images/<imgid>/metadata/ allows only POST, GET
+        response = self.myput('images/42/metadata', '', '')
+        self.assertMethodNotAllowed(response)
+        response = self.mydelete('images/42/metadata')
+        self.assertMethodNotAllowed(response)
+
+        # /images/<imgid>/metadata/<key> allows only PUT, GET, DELETE
+        response = self.mypost('images/42/metadata/foo')
+        self.assertMethodNotAllowed(response)
+
+
+@patch('synnefo.plankton.backend.ImageBackend')
+class ImageMetadataAPITest(ComputeAPITest):
+    def setUp(self):
+        self.image = {'id': 42,
+                 'name': 'image-1',
+                 'status': 'available',
+                 'created_at': '2012-11-26 11:52:54',
+                 'updated_at': '2012-12-26 11:52:54',
+                 'deleted_at': '',
+                 'properties': {'foo': 'bar', 'foo2': 'bar2'}}
+        self.result_image = \
+                  {'id': 42,
+                   'name': 'image-1',
+                   'status': 'ACTIVE',
+                   'progress': 100,
+                   'created': '2012-11-26T11:52:54+00:00',
+                   'updated': '2012-12-26T11:52:54+00:00',
+                   'metadata': {'foo': 'bar'}}
+        super(ImageMetadataAPITest, self).setUp()
+
+    @assert_backend_closed
+    def test_list_metadata(self, backend):
+        backend.return_value.get_image.return_value = self.image
+        response = self.myget('images/42/metadata', 'user')
+        self.assertSuccess(response)
+        meta = json.loads(response.content)['metadata']
+        self.assertEqual(meta, self.image['properties'])
+
+    @assert_backend_closed
+    def test_get_metadata(self, backend):
+        backend.return_value.get_image.return_value = self.image
+        response = self.myget('images/42/metadata/foo', 'user')
+        self.assertSuccess(response)
+        meta = json.loads(response.content)['meta']
+        self.assertEqual(meta['foo'], 'bar')
+
+    @assert_backend_closed
+    def test_get_invalid_metadata(self, backend):
+        backend.return_value.get_image.return_value = self.image
+        response = self.myget('images/42/metadata/not_found', 'user')
+        self.assertItemNotFound(response)
+
+    def test_delete_metadata_item(self, backend):
+        backend.return_value.get_image.return_value = self.image
+        response = self.mydelete('images/42/metadata/foo', 'user')
+        self.assertEqual(response.status_code, 204)
+        backend.return_value.update_metadata.assert_called_once_with('42', {'properties': {'foo2':
+                                                    'bar2'}})
+
+    @assert_backend_closed
+    def test_create_metadata_item(self, backend):
+        backend.return_value.get_image.return_value = self.image
+        request = {'meta': {'foo3': 'bar3'}}
+        response = self.myput('images/42/metadata/foo3', 'user',
+                              json.dumps(request), 'json')
+        self.assertEqual(response.status_code, 201)
+        backend.return_value.update_metadata.assert_called_once_with('42',
+                {'properties':
+                    {'foo': 'bar', 'foo2': 'bar2', 'foo3': 'bar3'}})
+
+    @assert_backend_closed
+    def test_create_metadata_malformed_1(self, backend):
+        backend.return_value.get_image.return_value = self.image
+        request = {'met': {'foo3': 'bar3'}}
+        response = self.myput('images/42/metadata/foo3', 'user',
+                              json.dumps(request), 'json')
+        self.assertBadRequest(response)
+
+    @assert_backend_closed
+    def test_create_metadata_malformed_2(self, backend):
+        backend.return_value.get_image.return_value = self.image
+        request = {'metadata': [('foo3', 'bar3')]}
+        response = self.myput('images/42/metadata/foo3', 'user',
+                              json.dumps(request), 'json')
+        self.assertBadRequest(response)
+
+    @assert_backend_closed
+    def test_create_metadata_malformed_3(self, backend):
+        backend.return_value.get_image.return_value = self.image
+        request = {'met': {'foo3': 'bar3', 'foo4': 'bar4'}}
+        response = self.myput('images/42/metadata/foo3', 'user',
+                                json.dumps(request), 'json')
+        self.assertBadRequest(response)
+
+    @assert_backend_closed
+    def test_create_metadata_malformed_4(self, backend):
+        backend.return_value.get_image.return_value = self.image
+        request = {'met': {'foo3': 'bar3'}}
+        response = self.myput('images/42/metadata/foo4', 'user',
+                              json.dumps(request), 'json')
+        self.assertBadRequest(response)
+
+    @assert_backend_closed
+    def test_update_metadata_item(self, backend):
+        backend.return_value.get_image.return_value = self.image
+        request = {'metadata': {'foo': 'bar_new', 'foo4': 'bar4'}}
+        response = self.mypost('images/42/metadata', 'user',
+                               json.dumps(request), 'json')
+        self.assertEqual(response.status_code, 201)
+        backend.return_value.update_metadata.assert_called_once_with('42',
+                {'properties':
+                    {'foo': 'bar_new', 'foo2': 'bar2', 'foo4': 'bar4'}
+                })
+
+    @assert_backend_closed
+    def test_update_metadata_malformed(self, backend):
+        backend.return_value.get_image.return_value = self.image
+        request = {'meta': {'foo': 'bar_new', 'foo4': 'bar4'}}
+        response = self.mypost('images/42/metadata', 'user',
+                               json.dumps(request), 'json')
+        self.assertBadRequest(response)
diff --git a/snf-cyclades-app/synnefo/api/tests/networks.py b/snf-cyclades-app/synnefo/api/tests/networks.py
new file mode 100644
index 0000000..8d2e661
--- /dev/null
+++ b/snf-cyclades-app/synnefo/api/tests/networks.py
@@ -0,0 +1,463 @@
+# Copyright 2012 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.
+
+import json
+from mock import patch
+
+from snf_django.utils.testing import BaseAPITest, mocked_quotaholder
+from synnefo.db.models import Network, NetworkInterface
+from synnefo.db import models_factory as mfactory
+from synnefo.cyclades_settings import cyclades_services
+from synnefo.lib.services import get_service_path
+from synnefo.lib import join_urls
+
+
+class ComputeAPITest(BaseAPITest):
+    def __init__(self, *args, **kwargs):
+        super(ComputeAPITest, self).__init__(*args, **kwargs)
+        self.compute_path = get_service_path(cyclades_services, 'compute',
+                                             version='v2.0')
+
+    def myget(self, path, *args, **kwargs):
+        path = join_urls(self.compute_path, path)
+        return self.get(path, *args, **kwargs)
+
+    def myput(self, path, *args, **kwargs):
+        path = join_urls(self.compute_path, path)
+        return self.put(path, *args, **kwargs)
+
+    def mypost(self, path, *args, **kwargs):
+        path = join_urls(self.compute_path, path)
+        return self.post(path, *args, **kwargs)
+
+    def mydelete(self, path, *args, **kwargs):
+        path = join_urls(self.compute_path, path)
+        return self.delete(path, *args, **kwargs)
+
+
+@patch('synnefo.logic.rapi_pool.GanetiRapiClient')
+class NetworkAPITest(ComputeAPITest):
+    def setUp(self):
+        self.mac_prefixes = mfactory.MacPrefixPoolTableFactory()
+        self.bridges = mfactory.BridgePoolTableFactory(base="link")
+        self.user = 'dummy-user'
+        self.net1 = mfactory.NetworkFactory(userid=self.user)
+        self.vm1 = mfactory.VirtualMachineFactory(userid=self.user)
+        self.nic1 = mfactory.NetworkInterfaceFactory(network=self.net1,
+                                                     machine=self.vm1)
+        self.nic2 = mfactory.NetworkInterfaceFactory(network=self.net1,
+                                                     machine=self.vm1)
+        self.net2 = mfactory.NetworkFactory(userid=self.user)
+        self.nic3 = mfactory.NetworkInterfaceFactory(network=self.net2)
+        super(NetworkAPITest, self).setUp()
+
+    def assertNetworksEqual(self, db_net, api_net, detail=False):
+        self.assertEqual(str(db_net.id), api_net["id"])
+        self.assertEqual(db_net.name, api_net['name'])
+        if detail:
+            self.assertEqual(db_net.state, api_net['status'])
+            self.assertEqual(db_net.flavor, api_net['type'])
+            self.assertEqual(db_net.subnet, api_net['cidr'])
+            self.assertEqual(db_net.subnet6, api_net['cidr6'])
+            self.assertEqual(db_net.gateway, api_net['gateway'])
+            self.assertEqual(db_net.gateway6, api_net['gateway6'])
+            self.assertEqual(db_net.dhcp, api_net['dhcp'])
+            self.assertEqual(db_net.public, api_net['public'])
+            db_nics = ["nic-%d-%d" % (nic.machine.id, nic.index) for nic in
+                       db_net.nics.filter(machine__userid=db_net.userid)]
+            self.assertEqual(db_nics, api_net['attachments'])
+
+    def test_create_network_1(self, mrapi):
+        request = {
+            'network': {'name': 'foo', "type": "MAC_FILTERED"}
+        }
+        with mocked_quotaholder():
+            response = self.mypost('networks/', 'user1',
+                                   json.dumps(request), 'json')
+        self.assertEqual(response.status_code, 202)
+        db_networks = Network.objects.filter(userid='user1')
+        self.assertEqual(len(db_networks), 1)
+        db_net = db_networks[0]
+        api_net = json.loads(response.content)['network']
+        self.assertNetworksEqual(db_net, api_net)
+        mrapi.CreateNetwork.assert_called()
+        mrapi.ConnectNetwork.assert_called()
+
+    def test_invalid_data_1(self, mrapi):
+        """Test invalid flavor"""
+        request = {
+            'network': {'name': 'foo', 'type': 'LoLo'}
+            }
+        response = self.mypost('networks/', 'user1',
+                               json.dumps(request), 'json')
+        self.assertBadRequest(response)
+        self.assertEqual(len(Network.objects.filter(userid='user1')), 0)
+
+    def test_invalid_data_2(self, mrapi):
+        """Test invalid data/subnet"""
+        request = {
+            'network': {'name': 'foo',
+                        'cidr': '10.0.0.0/8', "type":
+                        "MAC_FILTERED"}
+        }
+        response = self.mypost('networks/', 'user1',
+                               json.dumps(request), 'json')
+        self.assertFault(response, 413, "overLimit")
+
+    def test_invalid_data_3(self, mrapi):
+        """Test unauthorized to create public network"""
+        request = {
+                'network': {'name': 'foo',
+                            "public": "True",
+                            "type": "MAC_FILTERED"}
+            }
+        response = self.mypost('networks/', 'user1',
+                               json.dumps(request), 'json')
+        self.assertFault(response, 403, "forbidden")
+
+    def test_invalid_data_4(self, mrapi):
+        """Test unauthorized to create network not in settings"""
+        request = {
+                'network': {'name': 'foo', 'type': 'CUSTOM'}
+            }
+        response = self.mypost('networks/', 'user1',
+                               json.dumps(request), 'json')
+        self.assertFault(response, 403, "forbidden")
+
+    def test_invalid_subnet(self, mrapi):
+        """Test invalid subnet"""
+        request = {
+            'network': {'name': 'foo',
+                        'cidr': '10.0.0.10/27',
+                        "type": "MAC_FILTERED"}
+        }
+        response = self.mypost('networks/', 'user1',
+                               json.dumps(request), 'json')
+        self.assertBadRequest(response)
+
+    def test_invalid_gateway_1(self, mrapi):
+        request = {
+            'network': {'name': 'foo',
+                        'cidr': '10.0.0.0/28',
+                        'gateway': '10.0.0.0.300'}
+        }
+        response = self.mypost('networks/', 'user1',
+                               json.dumps(request), 'json')
+        self.assertBadRequest(response)
+
+    def test_invalid_gateway_2(self, mrapi):
+        request = {
+            'network': {'name': 'foo',
+                        'cidr': '10.0.0.0/28',
+                        'gateway': '10.2.0.1'}
+        }
+        response = self.mypost('networks/', 'user1',
+                               json.dumps(request), 'json')
+        self.assertBadRequest(response)
+
+    def test_invalid_network6(self, mrapi):
+        request = {
+            'network': {'name': 'foo',
+                        'cidr': '10.0.0.0/28',
+                        'subnet6': '10.0.0.0/28',
+                        'gateway': '10.2.0.1'}
+        }
+        response = self.mypost('networks/', 'user1',
+                               json.dumps(request), 'json')
+        self.assertBadRequest(response)
+
+    def test_invalid_gateway6(self, mrapi):
+        request = {
+            'network': {'name': 'foo',
+                        'cidr': '10.0.0.0/28',
+                        'subnet6': '2001:0db8:0123:4567:89ab:cdef:1234:5678',
+                        'gateway': '10.2.0.1'}
+        }
+        response = self.mypost('networks/', 'user1',
+                               json.dumps(request), 'json')
+        self.assertBadRequest(response)
+
+    def test_list_networks(self, mrapi):
+        """Test that expected list of networks is returned."""
+        # Create a deleted network
+        mfactory.NetworkFactory(userid=self.user, deleted=True)
+
+        response = self.myget('networks/', self.user)
+        self.assertSuccess(response)
+
+        db_nets = Network.objects.filter(userid=self.user, deleted=False)
+        api_nets = json.loads(response.content)["networks"]
+
+        self.assertEqual(len(db_nets), len(api_nets))
+        for api_net in api_nets:
+            net_id = api_net['id']
+            self.assertNetworksEqual(Network.objects.get(id=net_id), api_net)
+
+    def test_list_networks_detail(self, mrapi):
+        """Test that expected networks details are returned."""
+        # Create a deleted network
+        mfactory.NetworkFactory(userid=self.user, deleted=True)
+
+        response = self.myget('networks/detail', self.user)
+        self.assertSuccess(response)
+
+        db_nets = Network.objects.filter(userid=self.user, deleted=False)
+        api_nets = json.loads(response.content)["networks"]
+
+        self.assertEqual(len(db_nets), len(api_nets))
+        for api_net in api_nets:
+            net_id = api_net['id']
+            self.assertNetworksEqual(Network.objects.get(id=net_id), api_net,
+                                     detail=True)
+
+    def test_get_network_building_nics(self, mrapi):
+        net = mfactory.NetworkFactory()
+        machine = mfactory.VirtualMachineFactory(userid=net.userid)
+        mfactory.NetworkInterfaceFactory(network=net, machine=machine,
+                                         state="BUILDING")
+        response = self.myget('networks/%d' % net.id, net.userid)
+        self.assertSuccess(response)
+        api_net = json.loads(response.content)["network"]
+        self.assertEqual(len(api_net["attachments"]), 0)
+
+    def test_network_details_1(self, mrapi):
+        """Test that expected details for a network are returned"""
+        response = self.myget('networks/%d' % self.net1.id, self.net1.userid)
+        self.assertSuccess(response)
+        api_net = json.loads(response.content)["network"]
+        self.assertNetworksEqual(self.net1, api_net, detail=True)
+
+    def test_invalid_network(self, mrapi):
+        """Test details for non-existing network."""
+        response = self.myget('networks/%d' % 42, self.net1.userid)
+        self.assertItemNotFound(response)
+
+    def test_rename_network(self, mrapi):
+        request = {'network': {'name': "new_name"}}
+        response = self.myput('networks/%d' % self.net2.id,
+                              self.net2.userid, json.dumps(request), 'json')
+        self.assertEqual(response.status_code, 204)
+        self.assertEqual(Network.objects.get(id=self.net2.id).name, "new_name")
+        # Check invalid
+        request = {'name': "new_name"}
+        response = self.myput('networks/%d' % self.net2.id,
+                              self.net2.userid, json.dumps(request), 'json')
+        self.assertBadRequest(response)
+
+    def test_rename_deleted_network(self, mrapi):
+        net = mfactory.NetworkFactory(deleted=True)
+        request = {'network': {'name': "new_name"}}
+        response = self.myput('networks/%d' % net.id,
+                              net.userid, json.dumps(request), 'json')
+        self.assertBadRequest(response)
+
+    def test_rename_public_network(self, mrapi):
+        net = mfactory.NetworkFactory(public=True)
+        request = {'network': {'name': "new_name"}}
+        response = self.myput('networks/%d' % net.id,
+                              self.net2.userid, json.dumps(request), 'json')
+        self.assertFault(response, 403, 'forbidden')
+
+    def test_delete_network(self, mrapi):
+        net = mfactory.NetworkFactory(deleted=False, state='ACTIVE',
+                                      link="link-10")
+        with mocked_quotaholder():
+            response = self.mydelete('networks/%d' % net.id, net.userid)
+        self.assertEqual(response.status_code, 204)
+        net = Network.objects.get(id=net.id, userid=net.userid)
+        self.assertEqual(net.action, 'DESTROY')
+        mrapi.DeleteNetwork.assert_called()
+
+    def test_delete_public_network(self, mrapi):
+        net = mfactory.NetworkFactory(public=True)
+        response = self.mydelete('networks/%d' % net.id, self.net2.userid)
+        self.assertFault(response, 403, 'forbidden')
+        self.assertFalse(mrapi.called)
+
+    def test_delete_deleted_network(self, mrapi):
+        net = mfactory.NetworkFactory(deleted=True)
+        response = self.mydelete('networks/%d' % net.id, net.userid)
+        self.assertBadRequest(response)
+
+    def test_delete_network_in_use(self, mrapi):
+        net = self.net1
+        response = self.mydelete('networks/%d' % net.id, net.userid)
+        self.assertFault(response, 421, 'networkInUse')
+        self.assertFalse(mrapi.called)
+
+    def test_add_nic(self, mrapi):
+        user = 'userr'
+        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
+        net = mfactory.NetworkFactory(state='ACTIVE', userid=user)
+        mrapi().ModifyInstance.return_value = 1
+        request = {'add': {'serverRef': vm.id}}
+        response = self.mypost('networks/%d/action' % net.id,
+                               net.userid, json.dumps(request), 'json')
+        self.assertEqual(response.status_code, 202)
+
+    def test_add_nic_to_deleted_network(self, mrapi):
+        user = 'userr'
+        vm = mfactory.VirtualMachineFactory(name='yo', userid=user,
+                                            operstate="ACTIVE")
+        net = mfactory.NetworkFactory(state='ACTIVE', userid=user,
+                                      deleted=True)
+        request = {'add': {'serverRef': vm.id}}
+        response = self.mypost('networks/%d/action' % net.id,
+                               net.userid, json.dumps(request), 'json')
+        self.assertBadRequest(response)
+        self.assertFalse(mrapi.called)
+
+    def test_add_nic_to_public_network(self, mrapi):
+        user = 'userr'
+        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
+        net = mfactory.NetworkFactory(state='ACTIVE', userid=user, public=True)
+        request = {'add': {'serverRef': vm.id}}
+        response = self.mypost('networks/%d/action' % net.id,
+                               net.userid, json.dumps(request), 'json')
+        self.assertFault(response, 403, 'forbidden')
+        self.assertFalse(mrapi.called)
+
+    def test_add_nic_malformed_1(self, mrapi):
+        user = 'userr'
+        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
+        net = mfactory.NetworkFactory(state='ACTIVE', userid=user)
+        request = {'add': {'serveRef': vm.id}}
+        response = self.mypost('networks/%d/action' % net.id,
+                               net.userid, json.dumps(request), 'json')
+        self.assertBadRequest(response)
+        self.assertFalse(mrapi.called)
+
+    def test_add_nic_malformed_2(self, mrapi):
+        user = 'userr'
+        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
+        net = mfactory.NetworkFactory(state='ACTIVE', userid=user)
+        request = {'add': {'serveRef': [vm.id, 22]}}
+        response = self.mypost('networks/%d/action' % net.id,
+                               net.userid, json.dumps(request), 'json')
+        self.assertBadRequest(response)
+        self.assertFalse(mrapi.called)
+
+    def test_add_nic_not_active(self, mrapi):
+        """Test connecting VM to non-active network"""
+        user = 'dummy'
+        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
+        net = mfactory.NetworkFactory(state='PENDING', subnet='10.0.0.0/31',
+                                      userid=user)
+        request = {'add': {'serverRef': vm.id}}
+        response = self.mypost('networks/%d/action' % net.id,
+                               net.userid, json.dumps(request), 'json')
+        # Test that returns BuildInProgress
+        self.assertEqual(response.status_code, 409)
+        self.assertFalse(mrapi.called)
+
+    def test_add_nic_full_network(self, mrapi):
+        """Test connecting VM to a full network"""
+        user = 'userr'
+        vm = mfactory.VirtualMachineFactory(name='yo', userid=user,
+                                            operstate="STARTED")
+        net = mfactory.NetworkFactory(state='ACTIVE', subnet='10.0.0.0/30',
+                                      userid=user, dhcp=True)
+        pool = net.get_pool()
+        while not pool.empty():
+            pool.get()
+        pool.save()
+        pool = net.get_pool()
+        self.assertTrue(pool.empty())
+        request = {'add': {'serverRef': vm.id}}
+        response = self.mypost('networks/%d/action' % net.id,
+                               net.userid, json.dumps(request), 'json')
+        # Test that returns OverLimit
+        self.assertEqual(response.status_code, 413)
+        self.assertFalse(mrapi.called)
+
+    def test_remove_nic(self, mrapi):
+        user = 'userr'
+        vm = mfactory.VirtualMachineFactory(name='yo', userid=user,
+                                            operstate="ACTIVE")
+        net = mfactory.NetworkFactory(state='ACTIVE', userid=user)
+        nic = mfactory.NetworkInterfaceFactory(machine=vm, network=net)
+        mrapi().ModifyInstance.return_value = 1
+        request = {'remove': {'attachment': 'nic-%s-%s' % (vm.id, nic.index)}}
+        response = self.mypost('networks/%d/action' % net.id,
+                               net.userid, json.dumps(request), 'json')
+        self.assertEqual(response.status_code, 202)
+        self.assertTrue(NetworkInterface.objects.get(id=nic.id).dirty)
+        vm.task = None
+        vm.task_job_id = None
+        vm.save()
+        # Remove dirty nic
+        response = self.mypost('networks/%d/action' % net.id,
+                               net.userid, json.dumps(request), 'json')
+        self.assertFault(response, 409, 'buildInProgress')
+
+    def test_remove_nic_malformed(self, mrapi):
+        user = 'userr'
+        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
+        net = mfactory.NetworkFactory(state='ACTIVE', userid=user)
+        nic = mfactory.NetworkInterfaceFactory(machine=vm, network=net)
+        request = {'remove':
+                    {'att234achment': 'nic-%s-%s' % (vm.id, nic.index)}
+                  }
+        response = self.mypost('networks/%d/action' % net.id,
+                               net.userid, json.dumps(request), 'json')
+        self.assertBadRequest(response)
+
+    def test_remove_nic_malformed_2(self, mrapi):
+        user = 'userr'
+        vm = mfactory.VirtualMachineFactory(name='yo', userid=user)
+        net = mfactory.NetworkFactory(state='ACTIVE', userid=user)
+        request = {'remove':
+                    {'attachment': 'nic-%s' % vm.id}
+                  }
+        response = self.mypost('networks/%d/action' % net.id,
+                               net.userid, json.dumps(request), 'json')
+        self.assertBadRequest(response)
+
+    def test_catch_wrong_api_paths(self, *args):
+        response = self.myget('nonexistent')
+        self.assertEqual(response.status_code, 400)
+        try:
+            error = json.loads(response.content)
+        except ValueError:
+            self.assertTrue(False)
+
+    def test_method_not_allowed(self, *args):
+        # /networks/ allows only POST, GET
+        response = self.myput('networks', '', '')
+        self.assertMethodNotAllowed(response)
+        response = self.mydelete('networks')
+        self.assertMethodNotAllowed(response)
+
+        # /networks/<srvid>/ allows only GET, PUT, DELETE
+        response = self.mypost("networks/42")
+        self.assertMethodNotAllowed(response)
diff --git a/snf-cyclades-app/synnefo/api/tests/servers.py b/snf-cyclades-app/synnefo/api/tests/servers.py
new file mode 100644
index 0000000..3aa8b48
--- /dev/null
+++ b/snf-cyclades-app/synnefo/api/tests/servers.py
@@ -0,0 +1,683 @@
+# Copyright 2012 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.
+
+import json
+from copy import deepcopy
+
+from snf_django.utils.testing import (BaseAPITest, mocked_quotaholder,
+                                      override_settings)
+from synnefo.db.models import (VirtualMachine, VirtualMachineMetadata,
+                               FloatingIP)
+from synnefo.db import models_factory as mfactory
+from synnefo.logic.utils import get_rsapi_state
+from synnefo.cyclades_settings import cyclades_services
+from synnefo.lib.services import get_service_path
+from synnefo.lib import join_urls
+from synnefo import settings
+
+from mock import patch, Mock
+
+
+class ComputeAPITest(BaseAPITest):
+    def __init__(self, *args, **kwargs):
+        super(ComputeAPITest, self).__init__(*args, **kwargs)
+        self.compute_path = get_service_path(cyclades_services, 'compute',
+                                             version='v2.0')
+
+    def myget(self, path, *args, **kwargs):
+        path = join_urls(self.compute_path, path)
+        return self.get(path, *args, **kwargs)
+
+    def myput(self, path, *args, **kwargs):
+        path = join_urls(self.compute_path, path)
+        return self.put(path, *args, **kwargs)
+
+    def mypost(self, path, *args, **kwargs):
+        path = join_urls(self.compute_path, path)
+        return self.post(path, *args, **kwargs)
+
+    def mydelete(self, path, *args, **kwargs):
+        path = join_urls(self.compute_path, path)
+        return self.delete(path, *args, **kwargs)
+
+
+class ServerAPITest(ComputeAPITest):
+    def setUp(self):
+        self.user1 = 'user1'
+        self.user2 = 'user2'
+        self.vm1 = mfactory.VirtualMachineFactory(userid=self.user1)
+        self.vm2 = mfactory.VirtualMachineFactory(userid=self.user2)
+        self.vm3 = mfactory.VirtualMachineFactory(deleted=True,
+                                                  userid=self.user1)
+        self.vm4 = mfactory.VirtualMachineFactory(userid=self.user2)
+
+    def test_server_list_1(self):
+        """Test if the expected list of servers is returned."""
+        response = self.myget('servers')
+        self.assertSuccess(response)
+        servers = json.loads(response.content)['servers']
+        self.assertEqual(servers, [])
+
+    def test_server_list_2(self):
+        """Test if the expected list of servers is returned."""
+        response = self.myget('servers', self.user1)
+        self.assertSuccess(response)
+        servers = json.loads(response.content)['servers']
+        db_server = self.vm1
+        server = servers[0]
+        self.assertEqual(server["name"], db_server.name)
+        self.assertEqual(server["id"], db_server.id)
+
+    def test_server_list_detail(self):
+        """Test if the servers list details are returned."""
+        user = self.user2
+        user_vms = {self.vm2.id: self.vm2,
+                    self.vm4.id: self.vm4}
+
+        response = self.myget('servers/detail', user)
+        servers = json.loads(response.content)['servers']
+        self.assertEqual(len(servers), len(user_vms))
+        for api_vm in servers:
+            db_vm = user_vms[api_vm['id']]
+            self.assertEqual(api_vm['flavor']["id"], db_vm.flavor.id)
+            self.assertEqual(api_vm['hostId'], db_vm.hostid)
+            self.assertEqual(api_vm['id'], db_vm.id)
+            self.assertEqual(api_vm['image']["id"], db_vm.imageid)
+            self.assertEqual(api_vm['name'], db_vm.name)
+            self.assertEqual(api_vm['status'], get_rsapi_state(db_vm))
+            self.assertSuccess(response)
+
+    def test_server_detail(self):
+        """Test if a server details are returned."""
+        db_vm = self.vm2
+        user = self.vm2.userid
+        net = mfactory.NetworkFactory()
+        nic = mfactory.NetworkInterfaceFactory(machine=self.vm2, network=net,
+                                              ipv6="::babe")
+
+        db_vm_meta = mfactory.VirtualMachineMetadataFactory(vm=db_vm)
+
+        response = self.myget('servers/%d' % db_vm.id, user)
+        server = json.loads(response.content)['server']
+
+        self.assertEqual(server['flavor']["id"], db_vm.flavor.id)
+        self.assertEqual(server['hostId'], db_vm.hostid)
+        self.assertEqual(server['id'], db_vm.id)
+        self.assertEqual(server['image']["id"], db_vm.imageid)
+        self.assertEqual(server['name'], db_vm.name)
+        self.assertEqual(server['status'], get_rsapi_state(db_vm))
+        api_nic = server['attachments'][0]
+        self.assertEqual(api_nic['network_id'], str(net.id))
+        self.assertEqual(api_nic['mac_address'], nic.mac)
+        self.assertEqual(api_nic['firewallProfile'], nic.firewall_profile)
+        self.assertEqual(api_nic['ipv4'], nic.ipv4)
+        self.assertEqual(api_nic['ipv6'], nic.ipv6)
+        self.assertEqual(api_nic['OS-EXT-IPS:type'],"fixed")
+        self.assertEqual(api_nic['id'], 'nic-%s-%s' % (db_vm.id, nic.index))
+        api_address = server["addresses"]
+        self.assertEqual(api_address[str(net.id)],
+               [{"version": 4, "addr": nic.ipv4, "OS-EXT-IPS:type": "fixed"},
+                {"version": 6, "addr": nic.ipv6, "OS-EXT-IPS:type": "fixed"}])
+
+        metadata = server['metadata']
+        self.assertEqual(len(metadata), 1)
+        self.assertEqual(metadata[db_vm_meta.meta_key], db_vm_meta.meta_value)
+        self.assertSuccess(response)
+
+    def test_server_building_nics(self):
+        db_vm = self.vm2
+        user = self.vm2.userid
+        net1 = mfactory.NetworkFactory()
+        net2 = mfactory.NetworkFactory()
+        net3 = mfactory.NetworkFactory()
+        mfactory.NetworkInterfaceFactory(machine=self.vm2, network=net1,
+                                         state="BUILDING")
+        nic2 = mfactory.NetworkInterfaceFactory(machine=self.vm2, network=net2,
+                                                state="ACTIVE")
+        mfactory.NetworkInterfaceFactory(machine=self.vm2, network=net3,
+                                         state="BUILDING")
+
+        response = self.myget('servers/%d' % db_vm.id, user)
+        server = json.loads(response.content)['server']
+        nics = server["attachments"]
+        self.assertEqual(len(nics), 1)
+        self.assertEqual(nics[0]["network_id"], str(nic2.network_id))
+
+    def test_noauthorized(self):
+        """Test 404 for detail of other user vm"""
+        db_vm = self.vm2
+
+        response = self.myget('servers/%d' % db_vm.id, 'wrong_user')
+        self.assertItemNotFound(response)
+
+    def test_wrong_server(self):
+        """Test 404 response if server does not exist."""
+        response = self.myget('servers/%d' % 5000)
+        self.assertItemNotFound(response)
+
+    def test_create_server_empty(self):
+        """Test if the create server call returns a 400 badRequest if
+           no attributes are specified."""
+
+        response = self.mypost('servers', params={})
+        self.assertBadRequest(response)
+
+    def test_rename_server(self):
+        vm = self.vm2
+        request = {'server': {'name': 'new_name'}}
+        response = self.myput('servers/%d' % vm.id, vm.userid,
+                              json.dumps(request), 'json')
+        self.assertSuccess(response)
+        self.assertEqual(VirtualMachine.objects.get(id=vm.id).name, "new_name")
+
+    def test_catch_wrong_api_paths(self):
+        response = self.myget('nonexistent')
+        self.assertEqual(response.status_code, 400)
+        try:
+            error = json.loads(response.content)
+        except ValueError:
+            self.assertTrue(False)
+
+    def test_method_not_allowed(self, *args):
+        # /servers/ allows only POST, GET
+        response = self.myput('servers', '', '')
+        self.assertMethodNotAllowed(response)
+        response = self.mydelete('servers')
+        self.assertMethodNotAllowed(response)
+
+        # /servers/<srvid>/ allows only GET, PUT, DELETE
+        response = self.mypost("servers/42")
+        self.assertMethodNotAllowed(response)
+
+        # /imags/<srvid>/metadata/ allows only POST, GET
+        response = self.myput('servers/42/metadata', '', '')
+        self.assertMethodNotAllowed(response)
+        response = self.mydelete('servers/42/metadata')
+        self.assertMethodNotAllowed(response)
+
+        # /imags/<srvid>/metadata/ allows only POST, GET
+        response = self.myput('servers/42/metadata', '', '')
+        self.assertMethodNotAllowed(response)
+        response = self.mydelete('servers/42/metadata')
+        self.assertMethodNotAllowed(response)
+
+        # /imags/<srvid>/metadata/<key> allows only PUT, GET, DELETE
+        response = self.mypost('servers/42/metadata/foo')
+        self.assertMethodNotAllowed(response)
+
+
+fixed_image = Mock()
+fixed_image.return_value = {'location': 'pithos://foo',
+                            'checksum': '1234',
+                            "id": 1,
+                            "name": "test_image",
+                            'disk_format': 'diskdump'}
+
+
+@patch('synnefo.api.util.get_image', fixed_image)
+@patch('synnefo.logic.rapi_pool.GanetiRapiClient')
+class ServerCreateAPITest(ComputeAPITest):
+    def setUp(self):
+        self.flavor = mfactory.FlavorFactory()
+        # Create public network and backend
+        self.network = mfactory.NetworkFactory(public=True)
+        self.backend = mfactory.BackendFactory()
+        mfactory.BackendNetworkFactory(network=self.network,
+                                       backend=self.backend,
+                                       operstate="ACTIVE")
+        self.request = {
+                    "server": {
+                        "name": "new-server-test",
+                        "userid": "test_user",
+                        "imageRef": 1,
+                        "flavorRef": self.flavor.id,
+                        "metadata": {
+                            "My Server Name": "Apache1"
+                        },
+                        "personality": []
+                    }
+        }
+
+    def test_create_server(self, mrapi):
+        """Test if the create server call returns the expected response
+           if a valid request has been speficied."""
+
+        mrapi().CreateInstance.return_value = 12
+        with override_settings(settings, DEFAULT_INSTANCE_NETWORKS=[]):
+            with mocked_quotaholder():
+                response = self.mypost('servers', 'test_user',
+                                       json.dumps(self.request), 'json')
+        self.assertEqual(response.status_code, 202)
+        mrapi().CreateInstance.assert_called_once()
+
+        api_server = json.loads(response.content)['server']
+        self.assertEqual(api_server['status'], "BUILD")
+        self.assertEqual(api_server['progress'], 0)
+        self.assertEqual(api_server['metadata'],
+                        {"My Server Name":  "Apache1"})
+        self.assertTrue('adminPass' in api_server)
+
+        db_vm = VirtualMachine.objects.get(userid='test_user')
+        self.assertEqual(api_server['name'], db_vm.name)
+        self.assertEqual(api_server['status'], db_vm.operstate)
+
+        # Test drained flag in Network:
+        self.network.drained = True
+        self.network.save()
+        with mocked_quotaholder():
+            response = self.mypost('servers', 'test_user',
+                                   json.dumps(self.request), 'json')
+        self.assertEqual(response.status_code, 503, "serviceUnavailable")
+
+    def test_create_network_settings(self, mrapi):
+        mrapi().CreateInstance.return_value = 12
+        bnet1 = mfactory.BackendNetworkFactory(operstate="ACTIVE",
+                                               backend=self.backend)
+        bnet2 = mfactory.BackendNetworkFactory(operstate="ACTIVE",
+                                               backend=self.backend)
+        bnet3 = mfactory.BackendNetworkFactory(network__userid="test_user",
+                                               operstate="ACTIVE",
+                                               backend=self.backend)
+        bnet4 = mfactory.BackendNetworkFactory(network__userid="test_user",
+                                               operstate="ACTIVE",
+                                               backend=self.backend)
+        # User requested private networks
+        request = deepcopy(self.request)
+        request["server"]["networks"] = [bnet3.network.id, bnet4.network.id]
+        with override_settings(settings,
+                DEFAULT_INSTANCE_NETWORKS=["SNF:ANY_PUBLIC", bnet1.network.id,
+                                           bnet2.network.id]):
+            with mocked_quotaholder():
+                response = self.mypost('servers', 'test_user',
+                                       json.dumps(request), 'json')
+        self.assertEqual(response.status_code, 202)
+        name, args, kwargs = mrapi().CreateInstance.mock_calls[0]
+        self.assertEqual(len(kwargs["nics"]), 5)
+        self.assertEqual(kwargs["nics"][0]["network"],
+                         self.network.backend_id)
+        self.assertEqual(kwargs["nics"][1]["network"],
+                         bnet1.network.backend_id)
+        self.assertEqual(kwargs["nics"][2]["network"],
+                         bnet2.network.backend_id)
+        self.assertEqual(kwargs["nics"][3]["network"],
+                         bnet3.network.backend_id)
+        self.assertEqual(kwargs["nics"][4]["network"],
+                         bnet4.network.backend_id)
+
+        request["server"]["floating_ips"] = []
+        with override_settings(settings,
+                DEFAULT_INSTANCE_NETWORKS=[bnet2.network.id]):
+            with mocked_quotaholder():
+                response = self.mypost('servers', 'test_user',
+                                       json.dumps(request), 'json')
+        self.assertEqual(response.status_code, 202)
+        name, args, kwargs = mrapi().CreateInstance.mock_calls[1]
+        self.assertEqual(len(kwargs["nics"]), 3)
+        self.assertEqual(kwargs["nics"][0]["network"],
+                         bnet2.network.backend_id)
+        self.assertEqual(kwargs["nics"][1]["network"],
+                         bnet3.network.backend_id)
+        self.assertEqual(kwargs["nics"][2]["network"],
+                         bnet4.network.backend_id)
+
+        # test invalid network in DEFAULT_INSTANCE_NETWORKS
+        with override_settings(settings, DEFAULT_INSTANCE_NETWORKS=[42]):
+            response = self.mypost('servers', 'test_user',
+                                   json.dumps(request), 'json')
+        self.assertFault(response, 500, "internalServerError")
+
+        # test connect to public netwok
+        request = deepcopy(self.request)
+        request["server"]["networks"] = [self.network.id]
+        with override_settings(settings,
+                               DEFAULT_INSTANCE_NETWORKS=["SNF:ANY_PUBLIC"]):
+            response = self.mypost('servers', 'test_user',
+                                    json.dumps(request), 'json')
+        self.assertFault(response, 403, "forbidden")
+        # test wrong user
+        request = deepcopy(self.request)
+        request["server"]["networks"] = [bnet3.network.id]
+        with override_settings(settings,
+                               DEFAULT_INSTANCE_NETWORKS=["SNF:ANY_PUBLIC"]):
+            with mocked_quotaholder():
+                response = self.mypost('servers', 'dummy_user',
+                                       json.dumps(request), 'json')
+        self.assertItemNotFound(response)
+
+        # Test floating IPs
+        request = deepcopy(self.request)
+        request["server"]["networks"] = [bnet4.network.id]
+        network = mfactory.NetworkFactory(subnet="10.0.0.0/24")
+        mfactory.BackendNetworkFactory(network=network,
+                                       backend=self.backend,
+                                       operstate="ACTIVE")
+        fp1 = mfactory.FloatingIPFactory(ipv4="10.0.0.2",
+                                         userid="test_user",
+                                         network=network, machine=None)
+        fp2 = mfactory.FloatingIPFactory(ipv4="10.0.0.3", network=network,
+                                         userid="test_user",
+                                         machine=None)
+        request["server"]["floating_ips"] = [fp1.ipv4, fp2.ipv4]
+        with override_settings(settings,
+                DEFAULT_INSTANCE_NETWORKS=[bnet3.network.id]):
+            with mocked_quotaholder():
+                response = self.mypost('servers', 'test_user',
+                                     json.dumps(request), 'json')
+        self.assertEqual(response.status_code, 202)
+        api_server = json.loads(response.content)['server']
+        vm = VirtualMachine.objects.get(id=api_server["id"])
+        fp1 = FloatingIP.objects.get(id=fp1.id)
+        fp2 = FloatingIP.objects.get(id=fp2.id)
+        self.assertEqual(fp1.machine, vm)
+        self.assertEqual(fp2.machine, vm)
+        name, args, kwargs = mrapi().CreateInstance.mock_calls[2]
+        self.assertEqual(len(kwargs["nics"]), 4)
+        self.assertEqual(kwargs["nics"][0]["network"],
+                         bnet3.network.backend_id)
+        self.assertEqual(kwargs["nics"][1]["network"], network.backend_id)
+        self.assertEqual(kwargs["nics"][1]["ip"], fp1.ipv4)
+        self.assertEqual(kwargs["nics"][2]["network"], network.backend_id)
+        self.assertEqual(kwargs["nics"][2]["ip"], fp2.ipv4)
+        self.assertEqual(kwargs["nics"][3]["network"],
+                         bnet4.network.backend_id)
+
+    def test_create_server_no_flavor(self, mrapi):
+        request = deepcopy(self.request)
+        request["server"]["flavorRef"] = 42
+        with mocked_quotaholder():
+            response = self.mypost('servers', 'test_user',
+                                   json.dumps(request), 'json')
+        self.assertItemNotFound(response)
+
+
+@patch('synnefo.logic.rapi_pool.GanetiRapiClient')
+class ServerDestroyAPITest(ComputeAPITest):
+    def test_delete_server(self, mrapi):
+        vm = mfactory.VirtualMachineFactory()
+        mrapi().DeleteInstance.return_value = 12
+        response = self.mydelete('servers/%d' % vm.id, vm.userid)
+        self.assertEqual(response.status_code, 204)
+        mrapi().DeleteInstance.assert_called_once()
+
+    def test_non_existing_delete_server(self, mrapi):
+        vm = mfactory.VirtualMachineFactory()
+        response = self.mydelete('servers/%d' % 42, vm.userid)
+        self.assertItemNotFound(response)
+        self.assertFalse(mrapi.mock_calls)
+
+
+class ServerMetadataAPITest(ComputeAPITest):
+    def setUp(self):
+        self.vm = mfactory.VirtualMachineFactory()
+        self.metadata = mfactory.VirtualMachineMetadataFactory(vm=self.vm)
+        super(ServerMetadataAPITest, self).setUp()
+
+    def test_get_metadata(self):
+        vm = self.vm
+        create_meta = lambda: mfactory.VirtualMachineMetadataFactory(vm=vm)
+        metadata = [create_meta(), create_meta(), create_meta()]
+        response = self.myget('servers/%d/metadata' % vm.id, vm.userid)
+        self.assertTrue(response.status_code in [200, 203])
+        api_metadata = json.loads(response.content)['metadata']
+        self.assertEqual(len(api_metadata), len(metadata) + 1)
+        for db_m in metadata:
+            self.assertEqual(api_metadata[db_m.meta_key], db_m.meta_value)
+
+        request = {'metadata':
+                        {'foo': 'bar'},
+                        metadata[0].meta_key: 'bar2'
+                  }
+        response = self.mypost('servers/%d/metadata' % vm.id,
+                             vm.userid, json.dumps(request), 'json')
+        metadata2 = VirtualMachineMetadata.objects.filter(vm=vm)
+        response = self.myget('servers/%d/metadata' % vm.id, vm.userid)
+        self.assertTrue(response.status_code in [200, 203])
+        api_metadata2 = json.loads(response.content)['metadata']
+        self.assertTrue('foo' in api_metadata2.keys())
+        self.assertTrue(api_metadata2[metadata[0].meta_key], 'bar2')
+        self.assertEqual(len(api_metadata2), len(metadata2))
+        for db_m in metadata2:
+            self.assertEqual(api_metadata2[db_m.meta_key], db_m.meta_value)
+
+        # Create new meta
+        request = {'meta': {'foo2': 'bar2'}}
+        response = self.myput('servers/%d/metadata/foo2' % vm.id,
+                              vm.userid, json.dumps(request), 'json')
+
+        # Get the new meta
+        response = self.myget('servers/%d/metadata/foo2' % vm.id, vm.userid)
+        meta = json.loads(response.content)['meta']
+        self.assertEqual(meta['foo2'], 'bar2')
+
+        # Delete the new meta
+        response = self.mydelete('servers/%d/metadata/foo2' % vm.id, vm.userid)
+        self.assertEqual(response.status_code, 204)
+
+        # Try to get the deleted meta: should raise 404
+        response = self.myget('servers/%d/metadata/foo2' % vm.id, vm.userid)
+        self.assertEqual(response.status_code, 404)
+
+    def test_invalid_metadata(self):
+        vm = self.vm
+        response = self.mypost('servers/%d/metadata' % vm.id, vm.userid)
+        self.assertBadRequest(response)
+        self.assertEqual(len(vm.metadata.all()), 1)
+
+    def test_invalid_metadata_server(self):
+        response = self.mypost('servers/42/metadata', 'user')
+        self.assertItemNotFound(response)
+
+    def test_get_meta_invalid_key(self):
+        vm = self.vm
+        response = self.myget('servers/%d/metadata/foo2' % vm.id, vm.userid)
+        self.assertItemNotFound(response)
+
+
+@patch('synnefo.api.util.get_image')
+@patch('synnefo.logic.rapi_pool.GanetiRapiClient')
+class ServerActionAPITest(ComputeAPITest):
+    def test_actions(self, mrapi, mimage):
+        actions = ['start', 'shutdown', 'reboot']
+        vm = mfactory.VirtualMachineFactory()
+        vm.operstate = "STOPPED"
+        vm.save()
+        mrapi().StartupInstance.return_value = 0
+        mrapi().ShutdownInstance.return_value = 1
+        mrapi().RebootInstance.return_value = 2
+        for jobId, action in enumerate(actions):
+            if action in ["shutdown", "reboot"]:
+                vm.operstate = "STARTED"
+            else:
+                vm.operstate = "STOPPED"
+            vm.task = None
+            vm.task_job_id = None
+            vm.save()
+            val = {'type': 'HARD'} if action == 'reboot' else {}
+            request = {action: val}
+            response = self.mypost('servers/%d/action' % vm.id,
+                                   vm.userid, json.dumps(request), 'json')
+            self.assertEqual(response.status_code, 202)
+            if action == 'shutdown':
+                self.assertEqual(VirtualMachine.objects.get(id=vm.id).task,
+                                 "STOP")
+            else:
+                self.assertEqual(VirtualMachine.objects.get(id=vm.id).task,
+                                 action.upper())
+            self.assertEqual(VirtualMachine.objects.get(id=vm.id).task_job_id,
+                             jobId)
+
+    def test_action_in_building_vm(self, mrapi, mimage):
+        """Test building in progress"""
+        vm = mfactory.VirtualMachineFactory(operstate="BUILD")
+        request = {'start': {}}
+        with mocked_quotaholder():
+            response = self.mypost('servers/%d/action' % vm.id,
+                                   vm.userid, json.dumps(request), 'json')
+        self.assertEqual(response.status_code, 409)
+        self.assertFalse(mrapi.mock_calls)
+
+    def test_destroy_build_vm(self, mrapi, mimage):
+        """Test building in progress"""
+        vm = mfactory.VirtualMachineFactory()
+        mrapi().DeleteInstance.return_value = 2
+        response = self.mydelete('servers/%d' % vm.id,
+                                 vm.userid)
+        self.assertSuccess(response)
+        mrapi().RemoveInstance.assert_called_once()
+
+    def test_firewall(self, mrapi, mimage):
+        vm = mfactory.VirtualMachineFactory()
+        vm.operstate = "STOPPED"
+        vm.save()
+        request = {'firewallProfile': {'profile': 'PROTECTED'}}
+        response = self.mypost('servers/%d/action' % vm.id,
+                               vm.userid, json.dumps(request), 'json')
+        self.assertEqual(response.status_code, 202)
+        mrapi().ModifyInstance.assert_called_once()
+
+    def test_unsupported_firewall(self, mrapi, mimage):
+        vm = mfactory.VirtualMachineFactory()
+        vm.operstate = "STOPPED"
+        vm.save()
+        request = {'firewallProfile': {'profile': 'FOO'}}
+        response = self.mypost('servers/%d/action' % vm.id,
+                               vm.userid, json.dumps(request), 'json')
+        self.assertBadRequest(response)
+        self.assertFalse(mrapi.mock_calls)
+
+    def test_resize_vm(self, mrapi, mimage):
+        flavor = mfactory.FlavorFactory(cpu=1, ram=1024)
+        # Check building VM
+        vm = self.get_vm(flavor=flavor, operstate="BUILD")
+        request = {'resize': {'flavorRef': flavor.id}}
+        response = self.mypost('servers/%d/action' % vm.id,
+                             vm.userid, json.dumps(request), 'json')
+        self.assertFault(response, 409, "buildInProgress")
+        # Check same Flavor
+        vm = self.get_vm(flavor=flavor, operstate="STOPPED")
+        request = {'resize': {'flavorRef': flavor.id}}
+        response = self.mypost('servers/%d/action' % vm.id,
+                             vm.userid, json.dumps(request), 'json')
+        self.assertBadRequest(response)
+        # Check flavor with different disk
+        flavor2 = mfactory.FlavorFactory(disk=1024)
+        flavor3 = mfactory.FlavorFactory(disk=2048)
+        vm = self.get_vm(flavor=flavor2, operstate="STOPPED")
+        request = {'resize': {'flavorRef': flavor3.id}}
+        response = self.mypost('servers/%d/action' % vm.id,
+                             vm.userid, json.dumps(request), 'json')
+        self.assertBadRequest(response)
+        flavor2 = mfactory.FlavorFactory(disk_template="foo")
+        flavor3 = mfactory.FlavorFactory(disk_template="baz")
+        vm = self.get_vm(flavor=flavor2, operstate="STOPPED")
+        request = {'resize': {'flavorRef': flavor3.id}}
+        response = self.mypost('servers/%d/action' % vm.id,
+                             vm.userid, json.dumps(request), 'json')
+        self.assertBadRequest(response)
+        # Check success
+        vm = self.get_vm(flavor=flavor, operstate="STOPPED")
+        flavor4 = mfactory.FlavorFactory(disk_template=flavor.disk_template,
+                                         disk=flavor.disk,
+                                         cpu=4, ram=2048)
+        request = {'resize': {'flavorRef': flavor4.id}}
+        mrapi().ModifyInstance.return_value = 42
+        response = self.mypost('servers/%d/action' % vm.id,
+                             vm.userid, json.dumps(request), 'json')
+        self.assertEqual(response.status_code, 202)
+        vm = VirtualMachine.objects.get(id=vm.id)
+        self.assertEqual(vm.task_job_id, 42)
+        name, args, kwargs = mrapi().ModifyInstance.mock_calls[0]
+        self.assertEqual(kwargs["beparams"]["vcpus"], 4)
+        self.assertEqual(kwargs["beparams"]["minmem"], 2048)
+        self.assertEqual(kwargs["beparams"]["maxmem"], 2048)
+
+    def test_action_on_resizing_vm(self, mrapi, mimage):
+        vm = mfactory.VirtualMachineFactory()
+        vm.operstate = "RESIZE"
+        vm.save()
+        for action in VirtualMachine.ACTIONS:
+            request = {action[0]: ""}
+            response = self.mypost('servers/%d/action' % vm.id,
+                                 vm.userid, json.dumps(request), 'json')
+            self.assertBadRequest(response)
+        # however you can destroy
+        mrapi().DeleteInstance.return_value = 42
+        response = self.mydelete('servers/%d' % vm.id,
+                                 vm.userid)
+        self.assertSuccess(response)
+
+    def get_vm(self, flavor, operstate):
+        vm = mfactory.VirtualMachineFactory(flavor=flavor)
+        vm.operstate = operstate
+        vm.backendjobstatus = "success"
+        vm.save()
+        return vm
+
+
+class ServerVNCConsole(ComputeAPITest):
+    def test_not_active_server(self):
+        """Test console req for not ACTIVE server returns badRequest"""
+        vm = mfactory.VirtualMachineFactory(operstate="BUILD")
+        data = json.dumps({'console': {'type': 'vnc'}})
+        response = self.mypost('servers/%d/action' % vm.id,
+                               vm.userid, data, 'json')
+        self.assertBadRequest(response)
+
+    def test_active_server(self):
+        """Test console req for ACTIVE server"""
+        vm = mfactory.VirtualMachineFactory()
+        vm.operstate = 'STARTED'
+        vm.save()
+
+        data = json.dumps({'console': {'type': 'vnc'}})
+        with override_settings(settings, TEST=True):
+            response = self.mypost('servers/%d/action' % vm.id,
+                                   vm.userid, data, 'json')
+        self.assertEqual(response.status_code, 200)
+        reply = json.loads(response.content)
+        self.assertEqual(reply.keys(), ['console'])
+        console = reply['console']
+        self.assertEqual(console['type'], 'vnc')
+        self.assertEqual(set(console.keys()),
+                         set(['type', 'host', 'port', 'password']))
+
+    def test_wrong_console_type(self):
+        """Test console req for ACTIVE server"""
+        vm = mfactory.VirtualMachineFactory()
+        vm.operstate = 'STARTED'
+        vm.save()
+
+        data = json.dumps({'console': {'type': 'foo'}})
+        response = self.mypost('servers/%d/action' % vm.id,
+                               vm.userid, data, 'json')
+        self.assertBadRequest(response)
diff --git a/snf-cyclades-app/synnefo/api/tests/versions.py b/snf-cyclades-app/synnefo/api/tests/versions.py
new file mode 100644
index 0000000..ed06f96
--- /dev/null
+++ b/snf-cyclades-app/synnefo/api/tests/versions.py
@@ -0,0 +1,62 @@
+# Copyright 2012-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 django.utils import simplejson as json
+from django.test import TestCase
+from snf_django.utils.testing import astakos_user
+from synnefo.cyclades_settings import cyclades_services
+from synnefo.lib.services import get_service_path
+from synnefo.lib import join_urls
+
+
+class APITest(TestCase):
+    def test_api_version(self):
+        """Check API version."""
+        path = get_service_path(cyclades_services,
+                                'compute', version='v2.0')
+        with astakos_user('user'):
+            response = self.client.get(path)
+        self.assertEqual(response.status_code, 200)
+        api_version = json.loads(response.content)['version']
+        self.assertEqual(api_version['id'], 'v2.0')
+        self.assertEqual(api_version['status'], 'CURRENT')
+
+    def test_catch_wrong_api_paths(self, *args):
+        path = get_service_path(cyclades_services,
+                                'compute', version='v2.0')
+        response = self.client.get(join_urls(path, 'nonexistent'))
+        self.assertEqual(response.status_code, 400)
+        try:
+            error = json.loads(response.content)
+        except ValueError:
+            self.assertTrue(False)
