From f2f4aff1870fcf1647ca176db3b83be94cf1427f Mon Sep 17 00:00:00 2001 From: Chris Alfonso Date: Tue, 10 Apr 2012 16:58:45 -0400 Subject: [PATCH] Persisting resources --- heat/client.py | 2 -- heat/db/api.py | 5 +++++ heat/db/sqlalchemy/api.py | 20 +++++++++++++++++-- .../migrate_repo/versions/001_norwhal.py | 15 +++++++++++--- heat/db/sqlalchemy/models.py | 13 +++++++++--- heat/engine/manager.py | 15 ++++++++------ heat/engine/parser.py | 11 ++++++++-- heat/engine/resources.py | 13 +++++++++++- 8 files changed, 75 insertions(+), 19 deletions(-) diff --git a/heat/client.py b/heat/client.py index d914792352..5b88eb03dd 100644 --- a/heat/client.py +++ b/heat/client.py @@ -22,7 +22,6 @@ import logging import os from heat.common import client as base_client from heat.common import exception -import pdb from heat.cloudformations import * logger = logging.getLogger(__name__) @@ -60,7 +59,6 @@ class V1Client(base_client.BaseClient): params = self._extract_params(kwargs, SUPPORTED_PARAMS) self._insert_common_parameters(params) res = self.do_request("POST", "/CreateStack", params=params) - pdb.set_trace() data = json.loads(res.read()) return data diff --git a/heat/db/api.py b/heat/db/api.py index e149cfcb4f..b91ac892f9 100644 --- a/heat/db/api.py +++ b/heat/db/api.py @@ -64,6 +64,11 @@ def resource_get_all(context): def resource_create(context, values): return IMPL.resource_create(context, values) +def resource_get_all_by_stack(context, stack_id): + return IMPL.resource_get_all_by_stack(context, stack_id) + +def resource_get_by_name_and_stack(context, resource_name, stack_id): + return IMPL.resource_get_by_name_and_stack(context, resource_name, stack_id) def stack_get(context, stack_id): return IMPL.stack_get(context, stack_id) diff --git a/heat/db/sqlalchemy/api.py b/heat/db/sqlalchemy/api.py index 5783cd1e3a..cbdd4a714c 100644 --- a/heat/db/sqlalchemy/api.py +++ b/heat/db/sqlalchemy/api.py @@ -84,6 +84,13 @@ def resource_get(context, resource_id): return result +def resource_get_by_name_and_stack(context, resource_name, stack_id): + result = model_query(context, models.Resource).\ + filter_by(name=resource_name).\ + filter_by(stack_id=stack_id).first() + + return result + def resource_get_all(context): results = model_query(context, models.Resource).all() @@ -98,6 +105,15 @@ def resource_create(context, values): resource_ref.save() return resource_ref +def resource_get_all_by_stack(context, stack_id): + results = model_query(context, models.Resource).\ + filter_by(stack_id=stack_id).all() + + if not results: + raise Exception("no resources for stack_id %s were found" % stack_id) + + return results + def stack_get(context, stack_id): result = model_query(context, models.Stack).\ filter_by(name=stack_id).first() @@ -118,8 +134,8 @@ def stack_delete(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() + #for e in s.events: + # e.delete() s.delete() def event_get(context, event_id): diff --git a/heat/db/sqlalchemy/migrate_repo/versions/001_norwhal.py b/heat/db/sqlalchemy/migrate_repo/versions/001_norwhal.py index 5e7590af70..ba90c43de7 100644 --- a/heat/db/sqlalchemy/migrate_repo/versions/001_norwhal.py +++ b/heat/db/sqlalchemy/migrate_repo/versions/001_norwhal.py @@ -38,17 +38,26 @@ def upgrade(migrate_engine): resource = Table( 'resource', meta, Column('id', Integer, primary_key=True), - Column('instance_id', String(length=255, convert_unicode=False, + Column('nova_instance', String(length=255, convert_unicode=False, assert_unicode=None, unicode_error=None, _warn_on_bytestring=False)), + Column('name', String(length=255, convert_unicode=False, + assert_unicode=None, + unicode_error=None, _warn_on_bytestring=False)), + Column('created_at', DateTime(timezone=False)), Column('updated_at', DateTime(timezone=False)), - Column('state', Integer()), + Column('state', String(length=255, convert_unicode=False, + assert_unicode=None, + unicode_error=None, + _warn_on_bytestring=False)), Column('state_description', String(length=255, convert_unicode=False, assert_unicode=None, unicode_error=None, _warn_on_bytestring=False)), - Column('parsed_template_id', Integer, ForeignKey("parsed_template.id"), nullable=False), + Column('parsed_template_id', Integer, ForeignKey("parsed_template.id"), nullable=True), + Column('stack_id', Integer, ForeignKey("stack.id"), nullable=False), + Column('depends_on', Integer), ) parsedtemplate = Table( diff --git a/heat/db/sqlalchemy/models.py b/heat/db/sqlalchemy/models.py index efc5ed3012..51140b544e 100644 --- a/heat/db/sqlalchemy/models.py +++ b/heat/db/sqlalchemy/models.py @@ -16,7 +16,7 @@ SQLAlchemy models for heat data. """ from sqlalchemy import * -from sqlalchemy.orm import relationship, backref +from sqlalchemy.orm import relationship, backref, object_mapper from sqlalchemy.exc import IntegrityError from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.schema import ForeignKeyConstraint @@ -143,10 +143,17 @@ class Resource(BASE, HeatBase): __tablename__ = 'resource' id = Column(Integer, primary_key=True) - state = Column(String) + state = Column('state', String) + name = Column('name', String, nullable=False) + nova_instance = Column('nova_instance', String) state_description = Column('state_description', String) parsed_template_id = Column(Integer, ForeignKey('parsed_template.id'),\ - nullable=False) + nullable=True) parsed_template = relationship(ParsedTemplate, backref=backref('resources')) + stack_id = Column(Integer, ForeignKey('stack.id'),\ + nullable=False) + stack = relationship(Stack, backref=backref('resources'), cascade="all, delete", passive_deletes=True) + + depends_on = Column(Integer) diff --git a/heat/engine/manager.py b/heat/engine/manager.py index dd252c11ba..6cea4327c9 100644 --- a/heat/engine/manager.py +++ b/heat/engine/manager.py @@ -113,16 +113,19 @@ class EngineManager(manager.Manager): return res def delete_stack(self, context, stack_name, params): - s = db_api.stack_get(None, stack_name) - if not s: + st = db_api.stack_get(None, stack_name) + if not st: return {'Error': 'No stack by that name'} logger.info('deleting stack %s' % stack_name) - ps = parser.Stack(s.name, s.raw_template.template, params) - ps.stop() + rt = db_api.raw_template_get(None, st.raw_template_id) + ps = parser.Stack(st.name, rt.template, params) + resources = db_api.resource_get_all_by_stack(None, st.id) + for r in ps.resources: + ps.resources[r].stop() db_api.stack_delete(None, stack_name) - return None - + return list_stacks(context, stack_name, params) + def list_events(self, context, stack_name): return db_api.event_get_all_by_stack(None, stack_name) diff --git a/heat/engine/parser.py b/heat/engine/parser.py index c6878632c9..edacd14336 100644 --- a/heat/engine/parser.py +++ b/heat/engine/parser.py @@ -18,10 +18,11 @@ import json import logging from heat.engine import resources +from heat.db import api as db_api logger = logging.getLogger('heat.engine.parser') -class Stack: +class Stack(object): def __init__(self, stack_name, template, parms=None): self.id = 0 self.t = template @@ -41,7 +42,7 @@ class Stack: self.res = {} self.doc = None self.name = stack_name - + self.parms['AWS::Region'] = {"Description" : "AWS Regions", "Type" : "String", "Default" : "ap-southeast-1", "AllowedValues" : ["us-east-1","us-west-1","us-west-2","sa-east-1","eu-west-1","ap-southeast-1","ap-northeast-1"], "ConstraintDescription" : "must be a valid EC2 instance type." } @@ -53,6 +54,10 @@ class Stack: else: self.creds = parms['KeyStoneCreds'] + stack = db_api.stack_get(None, stack_name) + if stack: + self.id = stack.id + self.resources = {} for r in self.t['Resources']: type = self.t['Resources'][r]['Type'] @@ -155,9 +160,11 @@ class Stack: ''' order = self.get_create_order() order.reverse() + for r in order: try: self.resources[r].delete() + db_api.resource_get(None, self.resources[r].id).delete() except Exception as ex: logger.error('delete: %s' % str(ex)) self.resources[r].state_set(self.resources[r].DELETE_FAILED, str(ex)) diff --git a/heat/engine/resources.py b/heat/engine/resources.py index 6cecf88ad2..69a676404b 100644 --- a/heat/engine/resources.py +++ b/heat/engine/resources.py @@ -46,6 +46,11 @@ class Resource(object): self.stack = stack self.name = name self.instance_id = None + resource = db_api.resource_get_by_name_and_stack(None, name, stack.id) + if resource: + self.instance_id = resource.nova_instance + self.stack_id = stack.id + self._nova = {} if not self.t.has_key('Properties'): # make a dummy entry to prevent having to check all over the @@ -403,7 +408,13 @@ class Instance(Resource): if server.status == 'ACTIVE': self.state_set(self.CREATE_COMPLETE) self.instance_id = server.id - + rs = {} + rs['state'] = 'ACTIVE' + rs['nova_instance'] = self.instance_id + rs['stack_id'] = self.stack.id + rs['name'] = self.name + new_rs = db_api.resource_create(None, rs) + self.id = new_rs.id # just record the first ipaddress for n in server.networks: self.ipaddress = server.networks[n][0]