Integrating all stack, template, and event calls with database
This commit is contained in:
1
bin/heat
1
bin/heat
@@ -19,7 +19,6 @@ import base64
|
||||
import libxml2
|
||||
|
||||
from urlparse import urlparse
|
||||
|
||||
# If ../heat/__init__.py exists, add ../ to Python search path, so that
|
||||
# it will override what happens to be installed in /usr/(local/)lib/python...
|
||||
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
|
||||
@@ -216,11 +216,12 @@ if [ "${MYSQL_HEAT_PW}" != "${MYSQL_HEAT_PW_DEFAULT}" ] ; then
|
||||
fi
|
||||
|
||||
#create the schema using sqlalchemy-migrate
|
||||
if test $1 == "rpm"; then
|
||||
pushd /usr/lib/python2.7/site-packages/heat/db/sqlalchemy
|
||||
else
|
||||
#if [ $1='rpm' ];
|
||||
#then
|
||||
# pushd /usr/lib/python2.7/site-packages/heat/db/sqlalchemy
|
||||
#else
|
||||
pushd /usr/lib/python2.7/site-packages/heat-0.0.1-py2.7.egg/heat/db/sqlalchemy/
|
||||
fi
|
||||
#fi
|
||||
|
||||
python migrate_repo/manage.py version_control mysql://heat:heat@localhost/heat migrate_repo
|
||||
python manage.py upgrade
|
||||
|
||||
@@ -23,17 +23,14 @@ import os
|
||||
import socket
|
||||
import sys
|
||||
import urlparse
|
||||
|
||||
import webob
|
||||
from webob.exc import (HTTPNotFound,
|
||||
HTTPConflict,
|
||||
HTTPBadRequest)
|
||||
|
||||
from heat.common import wsgi
|
||||
from heat.common import config
|
||||
from heat import rpc
|
||||
from heat import context
|
||||
|
||||
logger = logging.getLogger('heat.api.v1.stacks')
|
||||
|
||||
|
||||
@@ -52,7 +49,9 @@ class StackController(object):
|
||||
Returns the following information for all stacks:
|
||||
"""
|
||||
con = context.get_admin_context()
|
||||
stack_list = rpc.call(con, 'engine', {'method': 'list_stacks'})
|
||||
stack_list = rpc.call(con, 'engine',
|
||||
{'method': 'list_stacks',
|
||||
'args': {'params': dict(req.params)}})
|
||||
|
||||
res = {'ListStacksResponse': {'ListStacksResult': {'StackSummaries': [] } } }
|
||||
summaries = res['ListStacksResponse']['ListStacksResult']['StackSummaries']
|
||||
@@ -69,7 +68,8 @@ class StackController(object):
|
||||
|
||||
stack_list = rpc.call(con, 'engine',
|
||||
{'method': 'show_stack',
|
||||
'args': {'stack_name': req.params['StackName']}})
|
||||
'args': {'stack_name': req.params['StackName'],
|
||||
'params': dict(req.params)}})
|
||||
res = {'DescribeStacksResult': {'Stacks': [] } }
|
||||
stacks = res['DescribeStacksResult']['Stacks']
|
||||
for s in stack_list['stacks']:
|
||||
@@ -160,7 +160,8 @@ class StackController(object):
|
||||
|
||||
res = rpc.call(con, 'engine',
|
||||
{'method': 'delete_stack',
|
||||
'args': {'stack_name': req.params['StackName']}})
|
||||
'args': {'stack_name': req.params['StackName'],
|
||||
'params': dict(req.params)}})
|
||||
|
||||
if res == None:
|
||||
return {'DeleteStackResult': ''}
|
||||
|
||||
@@ -20,12 +20,10 @@ Client classes for callers of a heat system
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
from heat.common import client as base_client
|
||||
from heat.common import exception
|
||||
|
||||
from heat.cloudformations import *
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ from heat.common import exception
|
||||
from heat.openstack.common import cfg
|
||||
from heat.openstack.common import utils
|
||||
|
||||
|
||||
bind_opts = [
|
||||
cfg.StrOpt('bind_host', default='0.0.0.0'),
|
||||
cfg.IntOpt('bind_port'),
|
||||
@@ -489,7 +488,6 @@ class Resource(object):
|
||||
method = getattr(obj, action)
|
||||
except AttributeError:
|
||||
method = getattr(obj, 'default')
|
||||
|
||||
return method(*args, **kwargs)
|
||||
|
||||
def get_action_args(self, request_environment):
|
||||
|
||||
@@ -97,4 +97,3 @@ def event_create(context, event):
|
||||
d[event['event_id']] = json.dumps(event)
|
||||
|
||||
d.close()
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ supported backend.
|
||||
'''
|
||||
|
||||
from heat.openstack.common import utils
|
||||
|
||||
def configure(conf):
|
||||
global IMPL
|
||||
global SQL_CONNECTION
|
||||
@@ -67,7 +66,7 @@ def resource_create(context, values):
|
||||
|
||||
|
||||
def stack_get(context, stack_id):
|
||||
return IMPL.resource_get(context, resource_id)
|
||||
return IMPL.stack_get(context, stack_id)
|
||||
|
||||
def stack_get_all(context):
|
||||
return IMPL.stack_get_all(context)
|
||||
@@ -75,6 +74,8 @@ def stack_get_all(context):
|
||||
def stack_create(context, values):
|
||||
return IMPL.stack_create(context, values)
|
||||
|
||||
def stack_delete(context, stack_name):
|
||||
return IMPL.stack_delete(context, stack_name)
|
||||
|
||||
def event_get(context, event_id):
|
||||
return IMPL.event_get(context, event_id)
|
||||
|
||||
@@ -20,33 +20,13 @@ from heat.db.sqlalchemy import models
|
||||
from heat.db.sqlalchemy.session import get_session
|
||||
|
||||
def model_query(context, *args, **kwargs):
|
||||
"""Query helper that accounts for context's `read_deleted` field.
|
||||
|
||||
:param context: context to query under
|
||||
"""
|
||||
:param session: if present, the session to use
|
||||
:param read_deleted: if present, overrides context's read_deleted field.
|
||||
:param project_only: if present and context is user-type, then restrict
|
||||
query to match the context's project_id.
|
||||
"""
|
||||
session = kwargs.get('session') or get_session()
|
||||
read_deleted = kwargs.get('read_deleted') or context.read_deleted
|
||||
project_only = kwargs.get('project_only')
|
||||
|
||||
query = session.query(*args)
|
||||
|
||||
if read_deleted == 'no':
|
||||
query = query.filter_by(deleted=False)
|
||||
elif read_deleted == 'yes':
|
||||
pass # omit the filter to include deleted and active
|
||||
elif read_deleted == 'only':
|
||||
query = query.filter_by(deleted=True)
|
||||
else:
|
||||
raise Exception(
|
||||
_("Unrecognized read_deleted value '%s'") % read_deleted)
|
||||
|
||||
if project_only and is_user_context(context):
|
||||
query = query.filter_by(project_id=context.project_id)
|
||||
|
||||
return query
|
||||
|
||||
def raw_template_get(context, template_id):
|
||||
@@ -120,19 +100,11 @@ def resource_create(context, values):
|
||||
|
||||
def stack_get(context, stack_id):
|
||||
result = model_query(context, models.Stack).\
|
||||
filter_by(id=stack_id).first()
|
||||
|
||||
if not result:
|
||||
raise Exception("stack with id %s not found" % stack_id)
|
||||
|
||||
filter_by(name=stack_id).first()
|
||||
return result
|
||||
|
||||
def stack_get_all(context):
|
||||
results = model_query(context, models.Stack).all()
|
||||
|
||||
if not results:
|
||||
raise Exception('no stacks were found')
|
||||
|
||||
return results
|
||||
|
||||
def stack_create(context, values):
|
||||
@@ -140,6 +112,15 @@ def stack_create(context, values):
|
||||
stack_ref.update(values)
|
||||
stack_ref.save()
|
||||
return stack_ref
|
||||
|
||||
def stack_delete(context, stack_name):
|
||||
s = stack_get(context, stack_name)
|
||||
if not s:
|
||||
raise Exception('Attempt to delete a stack with id: %s that does not exist' % stack_name)
|
||||
|
||||
for e in s.events:
|
||||
e.delete()
|
||||
s.delete()
|
||||
|
||||
def event_get(context, event_id):
|
||||
result = model_query(context, models.Event).\
|
||||
|
||||
@@ -21,6 +21,7 @@ def upgrade(migrate_engine):
|
||||
Column('name', String(length=255, convert_unicode=False,
|
||||
assert_unicode=None,
|
||||
unicode_error=None, _warn_on_bytestring=False)),
|
||||
Column('raw_template_id', Integer, ForeignKey("raw_template.id"), nullable=False),
|
||||
)
|
||||
|
||||
event = Table(
|
||||
@@ -47,17 +48,17 @@ def upgrade(migrate_engine):
|
||||
assert_unicode=None,
|
||||
unicode_error=None,
|
||||
_warn_on_bytestring=False)),
|
||||
Column('parsed_template_id', Integer, ForeignKey("parsed_template.id"), nullable=False),
|
||||
)
|
||||
|
||||
parsedtemplate = Table(
|
||||
'parsed_template', meta,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('resource_id', Integer, ForeignKey("resource.id"),\
|
||||
nullable=False),
|
||||
Column('raw_template_id', Integer, ForeignKey("raw_template.id"), nullable=False),
|
||||
Column('template', Text()),
|
||||
)
|
||||
|
||||
tables = [rawtemplate, stack, event, resource, parsedtemplate]
|
||||
tables = [rawtemplate, stack, event, parsedtemplate, resource]
|
||||
for table in tables:
|
||||
try:
|
||||
table.create()
|
||||
@@ -73,6 +74,7 @@ def downgrade(migrate_engine):
|
||||
event = Table('event', meta, autoload=True)
|
||||
resource = Table('resource', meta, autoload=True)
|
||||
parsedtemplate = Table('parsed_template', meta, autoload=True)
|
||||
stack = Table('stack', meta, autoload=True)
|
||||
|
||||
for table in (rawtemplate, event, stack, parsedtemplate, resource):
|
||||
for table in (event, stack, resource, parsedtemplate, rawtemplate):
|
||||
table.drop()
|
||||
|
||||
@@ -16,15 +16,26 @@ SQLAlchemy models for heat data.
|
||||
"""
|
||||
|
||||
from sqlalchemy import *
|
||||
from sqlalchemy.orm import relationship, backref
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.schema import ForeignKeyConstraint
|
||||
|
||||
from sqlalchemy import types as types
|
||||
from json import dumps, loads
|
||||
from nova import utils
|
||||
from heat.db.sqlalchemy.session import get_session
|
||||
|
||||
BASE = declarative_base()
|
||||
|
||||
class Json(types.TypeDecorator, types.MutableType):
|
||||
impl=types.Text
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
return dumps(value)
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
return loads(value)
|
||||
|
||||
class HeatBase(object):
|
||||
"""Base class for Heat Models."""
|
||||
__table_args__ = {'mysql_engine': 'InnoDB'}
|
||||
@@ -88,14 +99,18 @@ class RawTemplate(BASE, HeatBase):
|
||||
|
||||
__tablename__ = 'raw_template'
|
||||
id = Column(Integer, primary_key=True)
|
||||
template = Text()
|
||||
template = Column(Json)
|
||||
parsed_template = relationship("ParsedTemplate",\
|
||||
uselist=False, backref="raw_template", cascade="all, delete", passive_deletes=True)
|
||||
|
||||
class ParsedTemplate(BASE, HeatBase):
|
||||
"""Represents a parsed template."""
|
||||
|
||||
__tablename__ = 'parsed_template'
|
||||
id = Column(Integer, primary_key=True)
|
||||
resource_id = Column('resource_id', Integer)
|
||||
template = Column(Json)
|
||||
raw_template_id = Column(Integer, ForeignKey('raw_template.id'),\
|
||||
nullable=False)
|
||||
|
||||
class Stack(BASE, HeatBase):
|
||||
"""Represents an generated by the heat engine."""
|
||||
@@ -103,7 +118,11 @@ class Stack(BASE, HeatBase):
|
||||
__tablename__ = 'stack'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String)
|
||||
name = Column(String, unique=True)
|
||||
raw_template_id = Column(Integer, ForeignKey('raw_template.id'),\
|
||||
nullable=False)
|
||||
raw_template = relationship(RawTemplate,
|
||||
backref=backref('stack'), cascade="all, delete", passive_deletes=True)
|
||||
|
||||
class Event(BASE, HeatBase):
|
||||
"""Represents an event generated by the heat engine."""
|
||||
@@ -111,7 +130,11 @@ class Event(BASE, HeatBase):
|
||||
__tablename__ = 'event'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
stack_id = Column(Integer)
|
||||
stack_id = Column(Integer, ForeignKey('stack.id'),\
|
||||
nullable=False)
|
||||
stack = relationship(Stack,
|
||||
backref=backref('events'), cascade="all, delete", passive_deletes=True)
|
||||
|
||||
name = Column(String)
|
||||
|
||||
class Resource(BASE, HeatBase):
|
||||
@@ -122,3 +145,8 @@ class Resource(BASE, HeatBase):
|
||||
id = Column(Integer, primary_key=True)
|
||||
state = Column(String)
|
||||
state_description = Column('state_description', String)
|
||||
parsed_template_id = Column(Integer, ForeignKey('parsed_template.id'),\
|
||||
nullable=False)
|
||||
parsed_template = relationship(ParsedTemplate,
|
||||
backref=backref('resources'))
|
||||
|
||||
|
||||
@@ -23,21 +23,12 @@ import tempfile
|
||||
import time
|
||||
import traceback
|
||||
import logging
|
||||
|
||||
from eventlet import greenthread
|
||||
|
||||
import heat.context
|
||||
from heat.common import exception
|
||||
import webob
|
||||
from heat import manager
|
||||
from heat.openstack.common import cfg
|
||||
from heat import rpc
|
||||
from heat.engine import parser
|
||||
from heat.db import api as db_api
|
||||
|
||||
logger = logging.getLogger('heat.engine.manager')
|
||||
|
||||
stack_db = {}
|
||||
|
||||
class EngineManager(manager.Manager):
|
||||
"""Manages the running instances from creation to destruction."""
|
||||
|
||||
@@ -45,57 +36,69 @@ class EngineManager(manager.Manager):
|
||||
"""Load configuration options and connect to the hypervisor."""
|
||||
pass
|
||||
|
||||
def list_stacks(self, context):
|
||||
def list_stacks(self, context, params):
|
||||
logger.info('context is %s' % context)
|
||||
res = {'stacks': [] }
|
||||
for s in stack_db:
|
||||
stacks = db_api.stack_get_all(None)
|
||||
for s in stacks:
|
||||
ps = parser.Stack(s.name, s.raw_template.template, params)
|
||||
mem = {}
|
||||
mem['stack_id'] = s
|
||||
mem['stack_name'] = s
|
||||
mem['created_at'] = 'now'
|
||||
mem['stack_id'] = s.id
|
||||
mem['stack_name'] = s.name
|
||||
mem['created_at'] = str(s.created_at)
|
||||
try:
|
||||
mem['template_description'] = stack_db[s].t['Description']
|
||||
mem['stack_status'] = stack_db[s].t['StackStatus']
|
||||
mem['template_description'] = s.template.description
|
||||
mem['stack_status'] = ps.t['StackStatus']
|
||||
except:
|
||||
mem['template_description'] = 'No description'
|
||||
mem['stack_status'] = 'unknown'
|
||||
res['stacks'].append(mem)
|
||||
|
||||
return res
|
||||
|
||||
def show_stack(self, context, stack_name):
|
||||
|
||||
|
||||
def show_stack(self, context, stack_name, params):
|
||||
res = {'stacks': [] }
|
||||
if stack_db.has_key(stack_name):
|
||||
s = db_api.stack_get(None, id)
|
||||
if s:
|
||||
ps = parser.Stack(s.name, s.raw_template.template, params)
|
||||
mem = {}
|
||||
mem['stack_id'] = stack_name
|
||||
mem['stack_name'] = stack_name
|
||||
mem['creation_at'] = 'TODO'
|
||||
mem['updated_at'] = 'TODO'
|
||||
mem['stack_id'] = s.id
|
||||
mem['stack_name'] = s.name
|
||||
mem['creation_at'] = s.created_at
|
||||
mem['updated_at'] = s.updated_at
|
||||
mem['NotificationARNs'] = 'TODO'
|
||||
mem['Outputs'] = stack_db[stack_name].get_outputs()
|
||||
mem['Parameters'] = stack_db[stack_name].t['Parameters']
|
||||
mem['Outputs'] = ps.get_outputs()
|
||||
mem['Parameters'] = ps.t['Parameters']
|
||||
mem['StackStatusReason'] = 'TODO'
|
||||
mem['TimeoutInMinutes'] = 'TODO'
|
||||
try:
|
||||
mem['TemplateDescription'] = stack_db[stack_name].t['Description']
|
||||
mem['StackStatus'] = stack_db[stack_name].t['StackStatus']
|
||||
mem['TemplateDescription'] = ps.t['Description']
|
||||
mem['StackStatus'] = ps.t['StackStatus']
|
||||
except:
|
||||
mem['TemplateDescription'] = 'No description'
|
||||
mem['StackStatus'] = 'unknown'
|
||||
res['stacks'].append(mem)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def create_stack(self, context, stack_name, template, params):
|
||||
if stack_db.has_key(stack_name):
|
||||
logger.info('template is %s' % template)
|
||||
if db_api.stack_get(None, stack_name):
|
||||
return {'Error': 'Stack already exists with that name.'}
|
||||
|
||||
logger.info('template is %s' % template)
|
||||
stack_db[stack_name] = parser.Stack(stack_name, template, params)
|
||||
stack_db[stack_name].create()
|
||||
|
||||
return {'stack': {'id': stack_name}}
|
||||
stack = parser.Stack(stack_name, template, params)
|
||||
rt = {}
|
||||
rt['template'] = template
|
||||
new_rt = db_api.raw_template_create(None, rt)
|
||||
s = {}
|
||||
s['name'] = stack_name
|
||||
s['raw_template_id'] = new_rt.id
|
||||
new_s = db_api.stack_create(None, s)
|
||||
stack.id = new_s.id
|
||||
stack.start()
|
||||
|
||||
return {'stack': {'id': new_s.id, 'name': new_s.name,\
|
||||
'created_at': new_s.created_at}}
|
||||
|
||||
def validate_template(self, req, body=None):
|
||||
|
||||
@@ -109,13 +112,16 @@ class EngineManager(manager.Manager):
|
||||
|
||||
return res
|
||||
|
||||
def delete_stack(self, context, stack_name):
|
||||
if not stack_db.has_key(stack_name):
|
||||
return {'Error': 'No stack by that name'}
|
||||
def delete_stack(self, context, stack_name, params):
|
||||
s = db_api.stack_get(None, stack_name)
|
||||
if not s:
|
||||
return {'Error': 'No stack by that name'}
|
||||
|
||||
logger.info('deleting stack %s' % stack_name)
|
||||
stack_db[stack_name].delete()
|
||||
del stack_db[stack_name]
|
||||
|
||||
ps = parser.Stack(s.name, s.raw_template.template, params)
|
||||
ps.stop()
|
||||
db_api.stack_delete(None, stack_name)
|
||||
return None
|
||||
|
||||
def list_events(self, context, stack_name):
|
||||
|
||||
@@ -23,6 +23,7 @@ from novaclient.v1_1 import client
|
||||
|
||||
from heat.common import exception
|
||||
from heat.db import api as db_api
|
||||
from heat.common.config import HeatEngineConfigOpts
|
||||
|
||||
logger = logging.getLogger('heat.engine.resources')
|
||||
|
||||
@@ -88,11 +89,10 @@ class Resource(object):
|
||||
ev['stack_id'] = self.stack.id
|
||||
ev['stack_name'] = self.stack.name
|
||||
ev['resource_status'] = new_state
|
||||
ev['name'] = new_state
|
||||
ev['resource_status_reason'] = reason
|
||||
ev['resource_type'] = self.t['Type']
|
||||
ev['resource_properties'] = self.t['Properties']
|
||||
new_stack = db_api.stack_create(None, ev)
|
||||
ev['stack_id'] = new_stack.id
|
||||
db_api.event_create(None, ev)
|
||||
self.state = new_state
|
||||
|
||||
@@ -412,21 +412,10 @@ class Instance(Resource):
|
||||
self.state_set(self.CREATE_FAILED)
|
||||
|
||||
def delete(self):
|
||||
|
||||
if self.state == self.DELETE_IN_PROGRESS or self.state == self.DELETE_COMPLETE:
|
||||
return
|
||||
self.state_set(self.DELETE_IN_PROGRESS)
|
||||
Resource.delete(self)
|
||||
|
||||
if self.instance_id == None:
|
||||
self.state_set(self.DELETE_COMPLETE)
|
||||
return
|
||||
|
||||
Resource.stop(self)
|
||||
server = self.nova().servers.get(self.instance_id)
|
||||
server.delete()
|
||||
self.instance_id = None
|
||||
self.state_set(self.DELETE_COMPLETE)
|
||||
|
||||
|
||||
def insert_package_and_services(self, r, new_script):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user