]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Add a user creds database table and associate stacks with username.
authorIan Main <imain@redhat.com>
Fri, 15 Jun 2012 00:46:12 +0000 (17:46 -0700)
committerIan Main <imain@redhat.com>
Fri, 15 Jun 2012 02:52:00 +0000 (19:52 -0700)
This patch takes the credentials passed in from the context and allows
you to store them in the database in the 'user_creds' table for later
use with HA operations.  It also adds a 'username' to the stack table
for direct comparison and user validation to support per-user stacks.

Thanks to Angus for fixing the tests for me :)

Signed-off-by: Ian Main <imain@redhat.com>
heat/db/api.py
heat/db/sqlalchemy/api.py
heat/db/sqlalchemy/migrate_repo/versions/005_user_creds.py [new file with mode: 0644]
heat/db/sqlalchemy/models.py
heat/engine/manager.py
heat/tests/test_stacks.py

index 665d1ee1606ac8458f7cc617aeedd7dac7ed7697..a44fa61a0ace530f17088c53e76fda0930fbc7d6 100644 (file)
@@ -103,6 +103,10 @@ def stack_get_all(context):
     return IMPL.stack_get_all(context)
 
 
+def stack_get_by_user(context):
+    return IMPL.stack_get_by_user(context)
+
+
 def stack_create(context, values):
     return IMPL.stack_create(context, values)
 
@@ -111,6 +115,14 @@ def stack_delete(context, stack_name):
     return IMPL.stack_delete(context, stack_name)
 
 
+def user_creds_create(context):
+    return IMPL.user_creds_create(context)
+
+
+def user_creds_get(context_id):
+    return IMPL.user_creds_get(context_id)
+
+
 def event_get(context, event_id):
     return IMPL.event_get(context, event_id)
 
index f98431cdba30ba8cc6d98b17ac1bde06be9ea1a0..f382d1d6b28d00069febd49394c12ad283b8c80b 100644 (file)
@@ -126,6 +126,9 @@ def resource_get_all_by_stack(context, stack_id):
 def stack_get(context, stack_id):
     result = model_query(context, models.Stack).\
                         filter_by(name=stack_id).first()
+    if result is not None and context is not None and\
+        result.username != context.username:
+        return None
     return result
 
 
@@ -134,6 +137,12 @@ def stack_get_all(context):
     return results
 
 
+def stack_get_by_user(context):
+    results = model_query(context, models.Stack).\
+                          filter_by(username=context.username).all()
+    return results
+
+
 def stack_create(context, values):
     stack_ref = models.Stack()
     stack_ref.update(values)
@@ -170,6 +179,20 @@ def stack_delete(context, stack_name):
     session.flush()
 
 
+def user_creds_create(values):
+    user_creds_ref = models.UserCreds()
+    user_creds_ref.update(values)
+    user_creds_ref.save()
+    return user_creds_ref
+
+
+def user_creds_get(user_creds_id):
+    result = model_query(None, models.UserCreds).\
+                        filter_by(id=user_creds_id).first()
+
+    return result
+
+
 def event_get(context, event_id):
     result = model_query(context, models.Event).\
                         filter_by(id=event_id).first()
diff --git a/heat/db/sqlalchemy/migrate_repo/versions/005_user_creds.py b/heat/db/sqlalchemy/migrate_repo/versions/005_user_creds.py
new file mode 100644 (file)
index 0000000..5e0bfcf
--- /dev/null
@@ -0,0 +1,68 @@
+from sqlalchemy import *
+from migrate import *
+
+
+def upgrade(migrate_engine):
+    meta = MetaData(bind=migrate_engine)
+
+    user_creds = Table(
+        'user_creds', meta,
+        Column('id', Integer, primary_key=True),
+        Column('created_at', DateTime(timezone=False)),
+        Column('updated_at', DateTime(timezone=False)),
+        Column('username', String(length=255, convert_unicode=False,
+                                  assert_unicode=None,
+                                  unicode_error=None,
+                                  _warn_on_bytestring=False)),
+        Column('password', String(length=255, convert_unicode=False,
+                                  assert_unicode=None,
+                                  unicode_error=None,
+                                  _warn_on_bytestring=False)),
+        Column('service_user', String(length=255, convert_unicode=False,
+                                      assert_unicode=None,
+                                      unicode_error=None,
+                                      _warn_on_bytestring=False)),
+        Column('service_password', String(length=255, convert_unicode=False,
+                                          assert_unicode=None,
+                                          unicode_error=None,
+                                          _warn_on_bytestring=False)),
+        Column('tenant', String(length=1024, convert_unicode=False,
+                                assert_unicode=None,
+                                unicode_error=None,
+                                _warn_on_bytestring=False)),
+        Column('auth_url', Text()),
+        Column('aws_auth_url', Text()),
+        Column('tenant_id', String(length=256, convert_unicode=False,
+                                assert_unicode=None,
+                                unicode_error=None,
+                                _warn_on_bytestring=False)),
+        Column('aws_creds', Text())
+    )
+
+    try:
+        user_creds.create()
+    except Exception:
+        meta.drop_all(tables=tables)
+        raise
+
+    stack = Table('stack', meta, autoload=True)
+
+    Column('username', String(length=256, convert_unicode=False,
+                              assert_unicode=None,
+                              unicode_error=None,
+                              _warn_on_bytestring=False)).create(stack)
+    Column('user_creds_id', Integer, ForeignKey("user_creds.id"),
+           nullable=False).create(stack)
+
+
+def downgrade(migrate_engine):
+    meta = MetaData()
+    meta.bind = migrate_engine
+
+    watch_rule = Table('user_creds', meta, autoload=True)
+    watch_rule.drop()
+
+    stack = Table('stack', meta, autoload=True)
+
+    stack.c.username.drop()
+    stack.c.user_creds_id.drop()
index c377bbfc00a33f064166f6c748988a88c752bfd4..eea66a37ea2429058114382ec7d475de2c07d214 100644 (file)
@@ -141,6 +141,29 @@ class Stack(BASE, HeatBase):
                             nullable=False)
     raw_template = relationship(RawTemplate,
         backref=backref('stack'))
+    username = Column(String)
+    user_creds_id = Column(Integer, ForeignKey('user_creds.id'),
+                           nullable=False)
+
+
+class UserCreds(BASE, HeatBase):
+    """
+    Represents user credentials and mirrors the 'context'
+    handed in by wsgi.
+    """
+
+    __tablename__ = 'user_creds'
+
+    id = Column(Integer, primary_key=True)
+    username = Column(String)
+    password = Column(String)
+    service_user = Column(String)
+    service_password = Column(String)
+    tenant = Column(String)
+    auth_url = Column(String)
+    aws_auth_url = Column(String)
+    tenant_id = Column(String)
+    aws_creds = Column(String)
 
 
 class Event(BASE, HeatBase):
index 299221363afbc2d883b8caa38e40114badf6738a..65fcb5ffc29877bd1a3312a165cfe7f39d9b502a 100644 (file)
@@ -118,7 +118,7 @@ class EngineManager(manager.Manager):
         self._authenticate(context)
 
         res = {'stacks': []}
-        stacks = db_api.stack_get_all(None)
+        stacks = db_api.stack_get_by_user(context)
         if stacks is None:
             return res
         for s in stacks:
@@ -146,7 +146,7 @@ class EngineManager(manager.Manager):
         self._authenticate(context)
 
         res = {'stacks': []}
-        s = db_api.stack_get(None, stack_name)
+        s = db_api.stack_get(context, stack_name)
         if s:
             ps = parser.Stack(context, s.name,
                               s.raw_template.parsed_template.template,
@@ -212,10 +212,14 @@ class EngineManager(manager.Manager):
         rt['stack_name'] = stack_name
         new_rt = db_api.raw_template_create(None, rt)
 
+        new_creds = db_api.user_creds_create(context.to_dict())
+
         s = {}
         s['name'] = stack_name
         s['raw_template_id'] = new_rt.id
-        new_s = db_api.stack_create(None, s)
+        s['user_creds_id'] = new_creds.id
+        s['username'] = context.username
+        new_s = db_api.stack_create(context, s)
         stack.id = new_s.id
 
         pt = {}
index ec8a64dfce36bfdf9908c267c1861c3c3940ee3a..c45123893ce4d2e1902615540cc742236d18423d 100644 (file)
@@ -9,6 +9,7 @@ import sqlalchemy
 from nose.plugins.attrib import attr
 from nose import with_setup
 
+from heat. common import context
 from heat.tests.v1_1 import fakes
 from heat.engine import instance as instances
 import heat.db as db_api
@@ -70,9 +71,14 @@ class stacksTest(unittest.TestCase):
         rt['template'] = stack.t
         rt['stack_name'] = stack.name
         new_rt = db_api.raw_template_create(None, rt)
+        ct = {'username': 'fred',
+                   'password': 'mentions_fruit'}
+        new_creds = db_api.user_creds_create(ct)
         s = {}
         s['name'] = stack.name
         s['raw_template_id'] = new_rt.id
+        s['user_creds_id'] = new_creds.id
+        s['username'] = ct['username']
         new_s = db_api.stack_create(None, s)
         stack.id = new_s.id
         pt = {}
@@ -93,9 +99,14 @@ class stacksTest(unittest.TestCase):
         rt['template'] = stack.t
         rt['stack_name'] = stack.name
         new_rt = db_api.raw_template_create(None, rt)
+        ct = {'username': 'fred',
+                   'password': 'mentions_fruit'}
+        new_creds = db_api.user_creds_create(ct)
         s = {}
         s['name'] = stack.name
         s['raw_template_id'] = new_rt.id
+        s['user_creds_id'] = new_creds.id
+        s['username'] = ct['username']
         new_s = db_api.stack_create(None, s)
         stack.id = new_s.id
         pt = {}
@@ -127,22 +138,32 @@ class stacksTest(unittest.TestCase):
             assert(result['ResourceProperties']['InstanceType'] == 'm1.large')
 
     def test_stack_list(self):
-        self.m.StubOutWithMock(manager.EngineManager, '_authenticate')
-        manager.EngineManager._authenticate(None).AndReturn(True)
         stack = self.start_wordpress_stack('test_stack_list')
         rt = {}
         rt['template'] = stack.t
         rt['stack_name'] = stack.name
         new_rt = db_api.raw_template_create(None, rt)
+        ct = {'username': 'fred',
+              'password': 'mentions_fruit'}
+        new_creds = db_api.user_creds_create(ct)
+
+        ctx = context.get_admin_context()
+        self.m.StubOutWithMock(ctx, 'username')
+        ctx.username = 'fred'
+        self.m.StubOutWithMock(manager.EngineManager, '_authenticate')
+        manager.EngineManager._authenticate(ctx).AndReturn(True)
+
         s = {}
         s['name'] = stack.name
         s['raw_template_id'] = new_rt.id
-        new_s = db_api.stack_create(None, s)
+        s['user_creds_id'] = new_creds.id
+        s['username'] = ct['username']
+        new_s = db_api.stack_create(ctx, s)
         stack.id = new_s.id
         pt = {}
         pt['template'] = stack.t
         pt['raw_template_id'] = new_rt.id
-        new_pt = db_api.parsed_template_create(None, pt)
+        new_pt = db_api.parsed_template_create(ctx, pt)
         instances.Instance.nova().AndReturn(self.fc)
         self.m.ReplayAll()
         stack.create_blocking()
@@ -152,10 +173,10 @@ class stacksTest(unittest.TestCase):
         params = {}
         parameters = {}
         t['Parameters']['KeyName']['Value'] = 'test'
-        stack = parser.Stack(None, 'test_stack_list', t, 0, params)
+        stack = parser.Stack(ctx, 'test_stack_list', t, 0, params)
 
         man = manager.EngineManager()
-        sl = man.list_stacks(None, params)
+        sl = man.list_stacks(ctx, params)
 
         assert(len(sl) > 0)
         for s in sl['stacks']: