Extract database out of project, add alembic config

Project: http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/commit/841364e9
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/tree/841364e9
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/diff/841364e9

Branch: refs/heads/master
Commit: 841364e96df7f2bbdc634a1b4026b5cda083d7ee
Parents: e03a7c4
Author: BroganD1993 <darrenbro...@hotmail.com>
Authored: Mon Jun 16 20:41:06 2014 +0100
Committer: BroganD1993 <darrenbro...@hotmail.com>
Committed: Mon Jun 16 20:41:06 2014 +0100

----------------------------------------------------------------------
 alembic.ini                         |  59 +++++++++++++++++++++++
 gstack/__init__.py                  |  22 ++++++---
 gstack/configure.py                 |  13 ++++++
 gstack/controllers/instances.py     |   1 -
 gstack/core.py                      |  49 ++++++++++++++++++++
 gstack/data/app.db                  | Bin 11264 -> 0 bytes
 gstack/helpers.py                   |   1 -
 gstack/models/accesstoken.py        |   7 +++
 gstack/models/client.py             |   5 ++
 gstack/models/refreshtoken.py       |   6 +++
 migrations/README                   |   1 +
 migrations/alembic.ini              |  57 +++++++++++++++++++++++
 migrations/env.py                   |  77 +++++++++++++++++++++++++++++++
 migrations/script.py.mako           |  22 +++++++++
 migrations/versions/76bb287a37d_.py |  60 ++++++++++++++++++++++++
 setup.py                            |   1 +
 16 files changed, 373 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/alembic.ini
----------------------------------------------------------------------
diff --git a/alembic.ini b/alembic.ini
new file mode 100644
index 0000000..f34bc98
--- /dev/null
+++ b/alembic.ini
@@ -0,0 +1,59 @@
+# A generic, single database configuration.
+
+[alembic]
+# path to migration scripts
+script_location = migrations
+
+# template used to generate migration files
+# file_template = %%(rev)s_%%(slug)s
+
+# max length of characters to apply to the
+# "slug" field
+#truncate_slug_length = 40
+
+# set to 'true' to run the environment during
+# the 'revision' command, regardless of autogenerate
+# revision_environment = false
+
+# set to 'true' to allow .pyc and .pyo files without
+# a source .py file to be detected as revisions in the
+# versions/ directory
+# sourceless = false
+
+sqlalchemy.url = driver://user:pass@localhost/dbname
+
+
+# Logging configuration
+[loggers]
+keys = root,sqlalchemy,alembic
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+qualname =
+
+[logger_sqlalchemy]
+level = WARN
+handlers =
+qualname = sqlalchemy.engine
+
+[logger_alembic]
+level = INFO
+handlers =
+qualname = alembic
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(levelname)-5.5s [%(name)s] %(message)s
+datefmt = %H:%M:%S

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/gstack/__init__.py
----------------------------------------------------------------------
diff --git a/gstack/__init__.py b/gstack/__init__.py
index acc141d..0fae091 100644
--- a/gstack/__init__.py
+++ b/gstack/__init__.py
@@ -21,6 +21,7 @@ import os
 import sys
 
 from flask import Flask
+from gstack.core import db
 from flask.ext.sqlalchemy import SQLAlchemy
 
 
@@ -35,28 +36,37 @@ def _load_config_file():
 
     return config_file
 
+def _load_database():
+    database_file = os.path.join(
+        os.path.expanduser('~'),
+        '.gstack/gstack.sqlite'
+    )
+
+    if not os.path.exists(database_file):
+        sys.exit('No database found, please run gstack-configure')
+
+    return 'sqlite:///' + database_file
+
 
 def configure_app(settings=None):
     app.config['DATA'] = os.path.abspath(os.path.dirname(__file__)) + '/data'
 
+    db.init_app(app)
+    database_uri = _load_database()
+
     if settings:
         app.config.from_object(settings)
     else:
         config_file = _load_config_file()
         app.config.from_pyfile(config_file)
 
-    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + \
-        os.path.join(app.config['DATA'], 'app.db')
+    app.config['SQLALCHEMY_DATABASE_URI'] = database_uri
 
 
 app = Flask(__name__)
 
-db = SQLAlchemy(app)
 publickey_storage = {}
 
 from gstack.controllers import *
 
-
 basedir = os.path.abspath(os.path.dirname(__file__))
-
-db.create_all()

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/gstack/configure.py
----------------------------------------------------------------------
diff --git a/gstack/configure.py b/gstack/configure.py
index 436dbd0..3b1bd0c 100644
--- a/gstack/configure.py
+++ b/gstack/configure.py
@@ -19,10 +19,14 @@
 
 import os
 
+from alembic import command
+from alembic.config import Config as AlembicConfig
+
 
 def main():
     config_folder = _create_config_folder()
     _create_config_file(config_folder)
+    _create_database()
 
 
 def _create_config_folder():
@@ -69,3 +73,12 @@ def _create_config_file(config_folder):
     config_file.write('CLOUDSTACK_PATH = \'%s\'\n' % cloudstack_path)
 
     config_file.close()
+
+def _create_database():
+    directory = os.path.join(os.path.dirname(__file__), '../migrations')
+    config = AlembicConfig(os.path.join(
+        directory,
+        'alembic.ini'
+    ))
+    config.set_main_option('script_location', directory)
+    command.upgrade(config, 'head', sql=False, tag=None)

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/gstack/controllers/instances.py
----------------------------------------------------------------------
diff --git a/gstack/controllers/instances.py b/gstack/controllers/instances.py
index 8c78eb2..465996a 100755
--- a/gstack/controllers/instances.py
+++ b/gstack/controllers/instances.py
@@ -295,7 +295,6 @@ def addinstance(authorization, projectid, zone):
     args = {}
     args['name'] = data['name']
     args['serviceoffering'] = data['machineType'].rsplit('/', 1)[1]
-    print args['serviceoffering']
     args['template'] = 
data['disks'][0]['initializeParams']['sourceImage'].rsplit('/', 1)[1]
     args['zone'] = zone
 

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/gstack/core.py
----------------------------------------------------------------------
diff --git a/gstack/core.py b/gstack/core.py
new file mode 100644
index 0000000..1b3ecf0
--- /dev/null
+++ b/gstack/core.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+# encoding: utf-8
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from flask_sqlalchemy import SQLAlchemy
+
+db = SQLAlchemy()
+
+
+class Service(object):
+    __model__ = None
+
+    def _isinstance(self, model, raise_error=True):
+        valid_type = isinstance(model, self.__model__)
+        if not valid_type and raise_error:
+            raise ValueError('%s is not of type %s' % (model, self.__model__))
+        return valid_type
+
+    def save(self, model):
+        self._isinstance(model)
+        db.session.add(model)
+        db.session.commit()
+        return model
+
+    def get(self, primarykey):
+        return self.__model__.query.get(primarykey)
+
+    def create(self, **kwargs):
+        return self.save(self.__model__(**kwargs))
+
+    def delete(self, model):
+        self._isinstance(model)
+        db.session.delete(model)
+        db.session.commit()
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/gstack/data/app.db
----------------------------------------------------------------------
diff --git a/gstack/data/app.db b/gstack/data/app.db
deleted file mode 100644
index 5d29940..0000000
Binary files a/gstack/data/app.db and /dev/null differ

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/gstack/helpers.py
----------------------------------------------------------------------
diff --git a/gstack/helpers.py b/gstack/helpers.py
index 556bf27..662fe8e 100644
--- a/gstack/helpers.py
+++ b/gstack/helpers.py
@@ -33,7 +33,6 @@ def create_response(data):
 def successful_response(**kwargs):
     content = render_template(**kwargs)
     response = make_response(content)
-    print response
     response.headers['Content-Type'] = 'application/json'
     return _create_response(response, '200')
 

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/gstack/models/accesstoken.py
----------------------------------------------------------------------
diff --git a/gstack/models/accesstoken.py b/gstack/models/accesstoken.py
index 8acac57..cb4d159 100644
--- a/gstack/models/accesstoken.py
+++ b/gstack/models/accesstoken.py
@@ -21,7 +21,14 @@ from gstack import db
 
 
 class AccessToken(db.Model):
+    __tablename__ = 'accesstoken'
     access_token = db.Column(db.String(100), primary_key=True, unique=True)
     client_id = db.Column(db.String(100), unique=True)
     expires_in = db.Column(db.Integer)
     data = db.Column(db.String(500))
+
+    def __init__(self, access_token, client_id, expires_in, data):
+        self.access_token = access_token
+        self.client_id = client_id
+        self.expires_in = expires_in
+        self.data = data

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/gstack/models/client.py
----------------------------------------------------------------------
diff --git a/gstack/models/client.py b/gstack/models/client.py
index f6d03dd..00a9fe6 100644
--- a/gstack/models/client.py
+++ b/gstack/models/client.py
@@ -21,5 +21,10 @@ from gstack import db
 
 
 class Client(db.Model):
+    __tablename__ = 'client'
     client_id = db.Column(db.String(100), primary_key=True, unique=True)
     client_secret = db.Column(db.String(100), unique=True)
+
+    def __init__(self, client_id, client_secret):
+        self.client_id = client_id
+        self.client_secret = client_secret

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/gstack/models/refreshtoken.py
----------------------------------------------------------------------
diff --git a/gstack/models/refreshtoken.py b/gstack/models/refreshtoken.py
index 0fba279..9b8bab0 100644
--- a/gstack/models/refreshtoken.py
+++ b/gstack/models/refreshtoken.py
@@ -21,6 +21,12 @@ from gstack import db
 
 
 class RefreshToken(db.Model):
+    __tablename__ = 'refreshtoken'
     refresh_token = db.Column(db.String(100), primary_key=True, unique=True)
     client_id = db.Column(db.String(100), unique=True)
     data = db.Column(db.String(500))
+
+    def __init__(self, refresh_token, client_id, data):
+        self.refresh_token = refresh_token
+        self.client_id = client_id
+        self.data = data

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/migrations/README
----------------------------------------------------------------------
diff --git a/migrations/README b/migrations/README
new file mode 100644
index 0000000..98e4f9c
--- /dev/null
+++ b/migrations/README
@@ -0,0 +1 @@
+Generic single-database configuration.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/migrations/alembic.ini
----------------------------------------------------------------------
diff --git a/migrations/alembic.ini b/migrations/alembic.ini
new file mode 100644
index 0000000..a2a4775
--- /dev/null
+++ b/migrations/alembic.ini
@@ -0,0 +1,57 @@
+# A generic, single database configuration.
+
+[alembic]
+# path to migration scripts
+script_location = .
+
+# template used to generate migration files
+# file_template = %%(rev)s_%%(slug)s
+
+# max length of characters to apply to the
+# "slug" field
+#truncate_slug_length = 40
+
+# set to 'true' to run the environment during
+# the 'revision' command, regardless of autogenerate
+# revision_environment = false
+
+# set to 'true' to allow .pyc and .pyo files without
+# a source .py file to be detected as revisions in the
+# versions/ directory
+# sourceless = false
+
+
+# Logging configuration
+[loggers]
+keys = root,sqlalchemy,alembic
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+qualname =
+
+[logger_sqlalchemy]
+level = WARN
+handlers =
+qualname = sqlalchemy.engine
+
+[logger_alembic]
+level = INFO
+handlers =
+qualname = alembic
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(levelname)-5.5s [%(name)s] %(message)s
+datefmt = %H:%M:%S

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/migrations/env.py
----------------------------------------------------------------------
diff --git a/migrations/env.py b/migrations/env.py
new file mode 100644
index 0000000..cab0b22
--- /dev/null
+++ b/migrations/env.py
@@ -0,0 +1,77 @@
+from __future__ import with_statement
+from alembic import context
+from sqlalchemy import engine_from_config, pool
+from logging.config import fileConfig
+
+import os
+from gstack.core import db
+
+# this is the Alembic Config object, which provides
+# access to the values within the .ini file in use.
+config = context.config
+
+# Interpret the config file for Python logging.
+# This line sets up loggers basically.
+fileConfig(config.config_file_name)
+
+
+# other values from the config, defined by the needs of env.py,
+# can be acquired:
+# my_important_option = config.get_main_option("my_important_option")
+# ... etc.
+
+database_file = os.path.join(
+    os.path.expanduser('~'),
+    '.gstack/gstack.sqlite'
+)
+
+config.set_main_option('sqlalchemy.url', 'sqlite:///' + database_file)
+
+
+def run_migrations_offline():
+    """Run migrations in 'offline' mode.
+
+    This configures the context with just a URL
+    and not an Engine, though an Engine is acceptable
+    here as well.  By skipping the Engine creation
+    we don't even need a DBAPI to be available.
+
+    Calls to context.execute() here emit the given string to the
+    script output.
+
+    """
+    url = config.get_main_option("sqlalchemy.url")
+    context.configure(url=url, target_metadata=target_metadata)
+
+    with context.begin_transaction():
+        context.run_migrations()
+
+def run_migrations_online():
+    """Run migrations in 'online' mode.
+
+    In this scenario we need to create an Engine
+    and associate a connection with the context.
+
+    """
+    engine = engine_from_config(
+                config.get_section(config.config_ini_section),
+                prefix='sqlalchemy.',
+                poolclass=pool.NullPool)
+
+    connection = engine.connect()
+    context.configure(
+                connection=connection,
+                target_metadata=db.metadata
+                )
+
+    try:
+        with context.begin_transaction():
+            context.run_migrations()
+    finally:
+        connection.close()
+
+if context.is_offline_mode():
+    run_migrations_offline()
+else:
+    run_migrations_online()
+

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/migrations/script.py.mako
----------------------------------------------------------------------
diff --git a/migrations/script.py.mako b/migrations/script.py.mako
new file mode 100644
index 0000000..9570201
--- /dev/null
+++ b/migrations/script.py.mako
@@ -0,0 +1,22 @@
+"""${message}
+
+Revision ID: ${up_revision}
+Revises: ${down_revision}
+Create Date: ${create_date}
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = ${repr(up_revision)}
+down_revision = ${repr(down_revision)}
+
+from alembic import op
+import sqlalchemy as sa
+${imports if imports else ""}
+
+def upgrade():
+    ${upgrades if upgrades else "pass"}
+
+
+def downgrade():
+    ${downgrades if downgrades else "pass"}

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/migrations/versions/76bb287a37d_.py
----------------------------------------------------------------------
diff --git a/migrations/versions/76bb287a37d_.py 
b/migrations/versions/76bb287a37d_.py
new file mode 100644
index 0000000..27e6df6
--- /dev/null
+++ b/migrations/versions/76bb287a37d_.py
@@ -0,0 +1,60 @@
+"""empty message
+
+Revision ID: 76bb287a37d
+Revises: None
+Create Date: 2014-06-16 19:15:05.475000
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '76bb287a37d'
+down_revision = None
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    op.create_table('accesstoken',
+        sa.Column('access_token', sa.String(length=255), nullable=False),
+        sa.Column(
+            'client_id',
+            sa.String(length=255),
+            nullable=True),
+        sa.Column(
+            'expires_in',
+            sa.String(length=255),
+            nullable=True),
+        sa.Column(
+            'data',
+            sa.String(length=255),
+            nullable=True),
+        sa.PrimaryKeyConstraint('access_token'),
+        sa.UniqueConstraint('client_id')
+    )
+    op.create_table('client',
+        sa.Column('client_id', sa.String(length=255), nullable=False),
+        sa.Column(
+            'client_secret',
+            sa.String(length=255),
+            nullable=True),
+        sa.PrimaryKeyConstraint('client_id'),
+        sa.UniqueConstraint('client_secret')
+    )
+    op.create_table('refreshtoken',
+        sa.Column('refresh_token', sa.String(length=255), nullable=False),
+        sa.Column(
+            'client_id',
+            sa.String(length=255),
+            nullable=True),
+        sa.Column(
+            'data',
+            sa.String(length=255),
+            nullable=True),
+        sa.PrimaryKeyConstraint('refresh_token'),
+        sa.UniqueConstraint('client_id')
+    )
+
+
+def downgrade():
+    pass

http://git-wip-us.apache.org/repos/asf/cloudstack-gcestack/blob/841364e9/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index e49f8be..13600cf 100755
--- a/setup.py
+++ b/setup.py
@@ -56,6 +56,7 @@ setup(
         "pyopenssl",
         "Flask-SQLAlchemy",
         "flask",
+        "alembic"
     ],
     classifiers=[
         'Development Status :: 3 - Alpha',

Reply via email to