Improve test coverage, clean operations
diff --git a/gstack/__init__.py b/gstack/__init__.py
index c4e0c6e..0624553 100644
--- a/gstack/__init__.py
+++ b/gstack/__init__.py
@@ -75,6 +75,7 @@
 
 def configure_app(settings=None):
     app.config['DATA'] = os.path.abspath(os.path.dirname(__file__)) + '/data'
+    app.config['PATH'] = 'compute/v1/projects/'
 
     db.init_app(app)
 
diff --git a/gstack/configure.py b/gstack/configure.py
index d67cf73..242e901 100644
--- a/gstack/configure.py
+++ b/gstack/configure.py
@@ -19,16 +19,16 @@
 
 import os
 import argparse
-import ConfigParser
 
 from alembic import command
+from ConfigParser import SafeConfigParser
 from alembic.config import Config as AlembicConfig
 
 
 def main():
     config_folder = _create_config_folder()
-    _create_config_file(config_folder)
     _create_database()
+    _create_config_file(config_folder)
 
 
 def _create_config_folder():
@@ -66,7 +66,7 @@
 
 
 def _modify_config_profile(config_file, profile):
-    config = ConfigParser.SafeConfigParser()
+    config = SafeConfigParser()
     config.read(config_file)
 
     if not config.has_section(profile):
diff --git a/gstack/controllers/instances.py b/gstack/controllers/instances.py
index 7ea1139..4694b14 100755
--- a/gstack/controllers/instances.py
+++ b/gstack/controllers/instances.py
@@ -184,13 +184,11 @@
         return errors.resource_not_found(func_route)
 
     else:
-        populated_response = operations.create_response(
+        return helpers.create_response(operations.create_async_response(
             projectid=projectid,
             operationid=deployment_result['deployvirtualmachineresponse']['jobid'],
             authorization=authorization
-        )
-
-    return helpers.create_response(data=populated_response)
+        ))
 
 
 @app.route('/compute/v1/projects/<projectid>/zones/<zone>/instances/<instance>', methods=['DELETE'])
@@ -209,10 +207,8 @@
         authorization.client_secret
     )
 
-    populated_response = operations.create_response(
+    return helpers.create_response(operations.create_async_response(
         projectid=projectid,
         operationid=deletion_result['destroyvirtualmachineresponse']['jobid'],
         authorization=authorization
-    )
-
-    return helpers.create_response(data=populated_response)
+    ))
diff --git a/gstack/controllers/operations.py b/gstack/controllers/operations.py
index 048595d..361c277 100644
--- a/gstack/controllers/operations.py
+++ b/gstack/controllers/operations.py
@@ -38,34 +38,35 @@
     return cloudstack_response
 
 
-def _delete_instance_response(async_result, projectid):
-    populated_response = {
-        'kind': 'compute#operation',
-        'insertTime': async_result['created'],
-        'operationType': 'delete',
-        'name': async_result['jobid'],
-        'startTime': async_result['created'],
-        'selfLink': urllib.unquote_plus(helpers.get_root_url() + url_for(
+def _get_instance_async_response(async_result, projectid, type):
+    response = {}
+    response['kind'] = 'compute#operation'
+    response['id'] = async_result['jobid']
+    response['operationType'] = type
+    response['name'] = async_result['jobid']
+    response['insertTime'] = async_result['created']
+    response['startTime'] = async_result['created']
+    response['selfLink'] = urllib.unquote_plus(
+        helpers.get_root_url() + url_for(
             'getoperations',
             projectid=projectid,
             operationid=async_result['jobid']
         ))
-    }
 
     if async_result['jobstatus'] is 0:
-        populated_response['targetLink'] = ''
-        populated_response['status'] = 'PENDING'
-        populated_response['progress'] = 0
+        response['targetLink'] = ''
+        response['status'] = 'PENDING'
+        response['progress'] = 0
     elif async_result['jobstatus'] is 1:
-        populated_response['status'] = 'DONE'
-        populated_response['zone'] = urllib.unquote_plus(
+        response['status'] = 'DONE'
+        response['zone'] = urllib.unquote_plus(
             helpers.get_root_url() +
             url_for(
                 'getzone',
                 projectid=projectid,
                 zone=async_result['jobresult']['virtualmachine']['zonename'],
             ))
-        populated_response['targetLink'] = urllib.unquote_plus(
+        response['targetLink'] = urllib.unquote_plus(
             helpers.get_root_url() +
             url_for(
                 'getinstance',
@@ -73,6 +74,26 @@
                 zone=async_result['jobresult']['virtualmachine']['zonename'],
                 instance=async_result['jobresult']['virtualmachine']['name']))
 
+    return response
+
+
+def _delete_instance_response(async_result, projectid):
+    populated_response = _get_instance_async_response(async_result, projectid, 'delete')
+    return populated_response
+
+
+def _create_instance_response(async_result, projectid, authorization):
+    populated_response = _get_instance_async_response(async_result, projectid, 'insert')
+    populated_response['user'] = async_result['userid']
+
+    if async_result['jobstatus'] is 1:
+        _add_sshkey_metadata(
+            authorization=authorization,
+            publickey=publickey_storage[projectid],
+            instanceid=async_result['jobresult']['virtualmachine']['id']
+        )
+    print populated_response
+
     return populated_response
 
 
@@ -82,7 +103,6 @@
     split_publickey = [l[i:i + n] for i in range(0, len(l), n)]
     i = 0
     for datasegment in split_publickey:
-        print datasegment
         _add_sshkey_metadata_segment(
             authorization, str(i) + '-sshkey-segment', datasegment, instanceid)
         i = i + 1
@@ -105,55 +125,7 @@
     )
 
 
-def _create_instance_response(async_result, projectid, authorization):
-    populated_response = {
-        'kind': 'compute#operation',
-        'id': async_result['jobid'],
-        'operationType': 'insert',
-        'name': async_result['jobid'],
-        'user': async_result['userid'],
-        'insertTime': async_result['created'],
-        'startTime': async_result['created'],
-        'selfLink': urllib.unquote_plus(helpers.get_root_url() + url_for(
-            'getoperations',
-            projectid=projectid,
-            operationid=async_result['jobid']
-        ))
-    }
-
-    if async_result['jobstatus'] is 0:
-        # handle pending case
-        populated_response['targetLink'] = ''
-        populated_response['status'] = 'PENDING'
-        populated_response['progress'] = 0
-    elif async_result['jobstatus'] is 1:
-        # handle successful case
-        populated_response['status'] = 'DONE'
-        populated_response['id'] = async_result['jobid']
-        populated_response['zone'] = urllib.unquote_plus(
-            helpers.get_root_url() +
-            url_for(
-                'getzone',
-                projectid=projectid,
-                zone=async_result['jobresult']['virtualmachine']['zonename'],
-            ))
-        populated_response['targetLink'] = urllib.unquote_plus(
-            helpers.get_root_url() +
-            url_for(
-                'getinstance',
-                projectid=projectid,
-                zone=async_result['jobresult']['virtualmachine']['zonename'],
-                instance=async_result['jobresult']['virtualmachine']['name']))
-        _add_sshkey_metadata(
-            authorization=authorization,
-            publickey=publickey_storage[projectid],
-            instanceid=async_result['jobresult']['virtualmachine']['id']
-        )
-
-    return populated_response
-
-
-def create_response(authorization, projectid, operationid):
+def create_async_response(authorization, projectid, operationid):
     async_result = _get_async_result(
         authorization=authorization,
         args={'jobId': operationid}
@@ -184,7 +156,7 @@
 @app.route('/compute/v1/projects/<projectid>/global/operations/<operationid>', methods=['GET'])
 @authentication.required
 def getoperations(authorization, operationid, projectid):
-    return helpers.create_response(create_response(
+    return helpers.create_response(create_async_response(
         authorization=authorization,
         operationid=operationid,
         projectid=projectid
diff --git a/setup.py b/setup.py
index 13600cf..770e70d 100755
--- a/setup.py
+++ b/setup.py
@@ -36,27 +36,32 @@
     return open(os.path.join(os.path.dirname(__file__), fname)).read().strip()
 
 setup(
-    name="gstack",
+    name='gstack',
     version=VERSION,
-    description="A GCE interface to Apache CloudStack",
-    author="Ian Duffy, Darren Brogan, Sebastien Goasguen",
-    author_email="ian@ianduffy.ie, brogand93@darrenbrogan.ie, runseb@gmail.com",
-    long_description="A Google Compute Engine compliant interface to the Apache CloudStack API",
-    url="https://github.com/NOPping/gstack",
-    platforms=("Any"),
-    license="LICENSE.txt",
-    package_data={'': ['LICENSE.txt', 'data/*'],
-                  'ec2stack': ['templates/*.json']},
+    description='A GCE interface to Apache CloudStack',
+    author='Ian Duffy, Darren Brogan, Sebastien Goasguen',
+    author_email='ian@ianduffy.ie, brogand93@darrenbrogan.ie, runseb@gmail.com',
+    long_description='A Google Compute Engine compliant interface to the Apache CloudStack API',
+    url='https://github.com/NOPping/gstack',
+    platforms=('Any'),
+    license='LICENSE.txt',
+    package_data={'': ['LICENSE.txt', 'data/*', 'migrations/*']},
     packages=[
-        "gstack", "gstack.controllers", "gstack.models",
-        "gstack.services", "gstack.data", "pyoauth2"],
+        'gstack',
+        'gstack.controllers',
+        'gstack.models',
+        'gstack.services',
+        'gstack.data',
+        'pyoauth2',
+        'migrations'],
+    include_package_data=True,
     install_requires=[
-        "requests==0.14",
-        "pycrypto==2.6",
-        "pyopenssl",
-        "Flask-SQLAlchemy",
-        "flask",
-        "alembic"
+        'requests==0.14',
+        'pycrypto==2.6',
+        'pyopenssl',
+        'Flask-SQLAlchemy',
+        'flask',
+        'alembic'
     ],
     classifiers=[
         'Development Status :: 3 - Alpha',
diff --git a/tests/data/destroy_vm_async_pending.json b/tests/data/destroy_vm_async_pending.json
new file mode 100644
index 0000000..65ec50c
--- /dev/null
+++ b/tests/data/destroy_vm_async_pending.json
@@ -0,0 +1,14 @@
+{
+    "queryasyncjobresultresponse": {
+        "jobprocstatus": 0,
+        "created": "2014-06-23T22:24:21+0200",
+        "cmd": "org.apache.cloudstack.api.command.user.vm.DestroyVMCmd",
+        "userid": "26a772da-dc25-4f2b-b0f1-e095e3717a30",
+        "jobstatus": 0,
+        "jobid": "678bbff2-3e45-4c6a-af5c-0859b8ab8170",
+        "jobresultcode": 0,
+        "jobinstanceid": "35de6b8f-8155-4843-bd84-dec137ff784e",
+        "jobinstancetype": "VirtualMachine",
+        "accountid": "ddbdf378-e8d9-47e0-964b-661d0d8414b8"
+    }
+}
diff --git a/tests/operations_tests.py b/tests/operations_tests.py
new file mode 100644
index 0000000..ac6ccb1
--- /dev/null
+++ b/tests/operations_tests.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+import mock
+
+from gstack.helpers import read_file
+from . import GStackAppTestCase
+
+class OperationsTestCase(GStackAppTestCase):
+
+    def test_query_operation(self):
+        get = mock.Mock()
+        get.return_value.text = read_file('tests/data/destroy_vm_async_pending.json')
+        get.return_value.status_code = 200
+
+        with mock.patch('requests.get', get):
+            headers = {'authorization': 'Bearer ' + str(GStackAppTestCase.access_token)}
+            response = self.get('/compute/v1/projects/exampleproject/global/operations/exampleoperation', headers=headers)
+
+        self.assert_ok(response)
\ No newline at end of file
diff --git a/tests/settings.py b/tests/settings.py
index 278c50d..e6f93ed 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -1,4 +1,3 @@
-PATH = 'compute/v1/projects/'
 GSTACK_BIND_ADDRESS = 'localhost'
 GSTACK_PORT = '5000'
 CLOUDSTACK_HOST = 'api.exoscale.ch'