From dfe12cbaba575620efac009597461a80110db9c9 Mon Sep 17 00:00:00 2001 From: Angus Salkeld Date: Mon, 16 Apr 2012 17:07:07 +1000 Subject: [PATCH] Fix a heap of pep8 errors ./run_tests.sh is much cleaner now. Signed-off-by: Angus Salkeld --- bin/run-parser.py | 3 +- heat/api/v1/__init__.py | 9 +- heat/api/v1/stacks.py | 20 +++-- heat/cloudformations.py | 6 +- heat/cloudinit/part-handler.py | 9 +- heat/common/config.py | 5 +- heat/common/exception.py | 15 +++- heat/common/utils.py | 5 +- heat/db/api.py | 22 ++++- heat/db/sqlalchemy/api.py | 32 +++++-- heat/db/sqlalchemy/manage.py | 3 +- .../migrate_repo/versions/001_norwhal.py | 17 ++-- heat/db/sqlalchemy/models.py | 24 ++++-- heat/db/sqlalchemy/session.py | 2 + heat/engine/__init__.py | 1 - heat/engine/manager.py | 14 +-- heat/engine/parser.py | 86 ++++++++----------- heat/engine/resources.py | 80 ++++++++++------- heat/manager.py | 2 - heat/rpc/__init__.py | 3 +- heat/rpc/impl_qpid.py | 5 +- heat/service.py | 5 +- heat/tests/examples/test1.py | 5 ++ heat/tests/examples/test2.py | 4 + heat/tests/examples/test3.py | 4 + 25 files changed, 248 insertions(+), 133 deletions(-) diff --git a/bin/run-parser.py b/bin/run-parser.py index 594271c9dc..80ea86c5dc 100755 --- a/bin/run-parser.py +++ b/bin/run-parser.py @@ -40,7 +40,8 @@ with open(filename) as f: # Don't immediately see a way to have key name as a parameter and also # file injection and monitoring # need to insert key on creation and know what private key is - setparam(params_dict, 'KeyName', 'sdake_key') # <- that gets inserted into image + setparam(params_dict, 'KeyName', 'sdake_key') + # ^ that gets inserted into image setparam(params_dict, 'AWS::StackName', stack_name) setparam(params_dict, 'InstanceType', 'm1.xlarge') diff --git a/heat/api/v1/__init__.py b/heat/api/v1/__init__.py index 8ce18894d6..25b1c87680 100644 --- a/heat/api/v1/__init__.py +++ b/heat/api/v1/__init__.py @@ -21,10 +21,12 @@ from heat.common import wsgi logger = logging.getLogger(__name__) + class API(wsgi.Router): - """WSGI router for Heat v1 API requests.""" - #TODO GetTemplate, ValidateTemplate + """ + WSGI router for Heat v1 API requests. + """ def __init__(self, conf, **local_conf): self.conf = conf @@ -49,6 +51,7 @@ class API(wsgi.Router): mapper.connect("/DescribeStackEvents", controller=stacks_resource, action="events_list", conditions=dict(method=["GET"])) mapper.connect("/ValidateTemplate", controller=stacks_resource, - action="validate_template", conditions=dict(method=["GET"])) + action="validate_template", + conditions=dict(method=["GET"])) super(API, self).__init__(mapper) diff --git a/heat/api/v1/stacks.py b/heat/api/v1/stacks.py index 11c135c8f5..c1deb0314b 100644 --- a/heat/api/v1/stacks.py +++ b/heat/api/v1/stacks.py @@ -56,8 +56,10 @@ class StackController(object): {'method': 'list_stacks', 'args': {'params': dict(req.params)}}) - res = {'ListStacksResponse': {'ListStacksResult': {'StackSummaries': [] } } } - summaries = res['ListStacksResponse']['ListStacksResult']['StackSummaries'] + res = {'ListStacksResponse': { + 'ListStacksResult': {'StackSummaries': []}}} + results = res['ListStacksResponse']['ListStacksResult'] + summaries = results['StackSummaries'] if stack_list != None: for s in stack_list['stacks']: summaries.append(s) @@ -79,7 +81,7 @@ class StackController(object): except rpc_common.RemoteError as ex: return webob.exc.HTTPBadRequest(str(ex)) - res = {'DescribeStacksResult': {'Stacks': [] } } + res = {'DescribeStacksResult': {'Stacks': []}} stacks = res['DescribeStacksResult']['Stacks'] for s in stack_list['stacks']: mem = {'member': s} @@ -88,10 +90,10 @@ class StackController(object): return res def _get_template(self, req): - if req.params.has_key('TemplateBody'): + if 'TemplateBody' in req.params: logger.info('TemplateBody ...') return req.params['TemplateBody'] - elif req.params.has_key('TemplateUrl'): + elif 'TemplateUrl' in req.params: logger.info('TemplateUrl %s' % req.params['TemplateUrl']) url = urlparse.urlparse(req.params['TemplateUrl']) if url.scheme == 'https': @@ -110,7 +112,6 @@ class StackController(object): return None - def create(self, req): """ Returns the following information for all stacks: @@ -142,7 +143,6 @@ class StackController(object): except rpc_common.RemoteError as ex: return webob.exc.HTTPBadRequest(str(ex)) - def validate_template(self, req): con = context.get_admin_context() @@ -187,7 +187,6 @@ class StackController(object): else: return {'DeleteStackResult': res['Error']} - def events_list(self, req): """ Returns the following information for all stacks: @@ -205,8 +204,11 @@ class StackController(object): return {'DescribeStackEventsResult': {'StackEvents': events}} + def create_resource(options): - """Stacks resource factory method.""" + """ + Stacks resource factory method. + """ deserializer = wsgi.JSONRequestDeserializer() serializer = wsgi.JSONResponseSerializer() return wsgi.Resource(StackController(options), deserializer, serializer) diff --git a/heat/cloudformations.py b/heat/cloudformations.py index c26a3a60e4..2bb00e03d4 100644 --- a/heat/cloudformations.py +++ b/heat/cloudformations.py @@ -13,7 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. -SUPPORTED_PARAMS = ('StackName', 'TemplateBody', 'TemplateUrl','NotificationARNs', 'Parameters', - 'Version', 'SignatureVersion', 'Timestamp', 'AWSAccessKeyId', +SUPPORTED_PARAMS = ('StackName', 'TemplateBody', 'TemplateUrl', + 'NotificationARNs', 'Parameters', 'Version', + 'SignatureVersion', 'Timestamp', 'AWSAccessKeyId', 'Signature', 'KeyStoneCreds') - diff --git a/heat/cloudinit/part-handler.py b/heat/cloudinit/part-handler.py index 6dfc89b26a..bf52efbac2 100644 --- a/heat/cloudinit/part-handler.py +++ b/heat/cloudinit/part-handler.py @@ -1,12 +1,15 @@ #part-handler + + def list_types(): return(["text/x-cfninitdata"]) -def handle_part(data,ctype,filename,payload): + +def handle_part(data, ctype, filename, payload): if ctype == "__begin__": - return + return if ctype == "__end__": - return + return if ctype == 'text/x-cfninitdata': f = open('/var/lib/cloud/data/%s' % filename, 'w') diff --git a/heat/common/config.py b/heat/common/config.py index 9987f1268f..98e6d8b5c9 100644 --- a/heat/common/config.py +++ b/heat/common/config.py @@ -140,6 +140,7 @@ class HeatConfigOpts(cfg.CommonConfigOpts): **kwargs) self.register_cli_opts(rpc_opts) + class HeatEngineConfigOpts(cfg.CommonConfigOpts): service_opts = [ @@ -178,7 +179,8 @@ class HeatEngineConfigOpts(cfg.CommonConfigOpts): help='port for os volume api to listen'), ] db_opts = [ - cfg.StrOpt('db_backend', default='heat.db.sqlalchemy.api', help='The backend to use for db'), + cfg.StrOpt('db_backend', default='heat.db.sqlalchemy.api', + help='The backend to use for db'), cfg.StrOpt('sql_connection', default='mysql://heat:heat@localhost/heat', help='The SQLAlchemy connection string used to connect to the ' @@ -209,6 +211,7 @@ class HeatEngineConfigOpts(cfg.CommonConfigOpts): self.register_cli_opts(self.service_opts) self.register_cli_opts(rpc_opts) + def setup_logging(conf): """ Sets up the logging options for a log with supplied name diff --git a/heat/common/exception.py b/heat/common/exception.py index 46ab31aa89..dd2eed5ee9 100644 --- a/heat/common/exception.py +++ b/heat/common/exception.py @@ -21,10 +21,12 @@ import functools import urlparse from heat.openstack.common.exception import * + class RedirectException(Exception): def __init__(self, url): self.url = urlparse.urlparse(url) + def wrap_exception(notifier=None, publisher_id=None, event_type=None, level=None): """This decorator wraps a method to catch any exceptions that may @@ -71,6 +73,7 @@ def wrap_exception(notifier=None, publisher_id=None, event_type=None, return functools.wraps(f)(wrapped) return inner + class MissingCredentialError(OpenstackException): message = _("Missing required credential: %(required)s") @@ -79,6 +82,7 @@ class BadAuthStrategy(OpenstackException): message = _("Incorrect auth strategy, expected \"%(expected)s\" but " "received \"%(received)s\"") + class AuthBadRequest(OpenstackException): message = _("Connect error/bad request to Auth service at URL %(url)s.") @@ -94,9 +98,11 @@ class AuthorizationFailure(OpenstackException): class NotAuthenticated(OpenstackException): message = _("You are not authenticated.") + class Forbidden(OpenstackException): message = _("You are not authorized to complete this action.") + #NOTE(bcwaldon): here for backwards-compatability, need to deprecate. class NotAuthorized(Forbidden): message = _("You are not authorized to complete this action.") @@ -119,6 +125,7 @@ class MultipleChoices(OpenstackException): "means that you have not included a version indicator in a " "request URI.\n\nThe body of response returned:\n%(body)s") + class LimitExceeded(OpenstackException): message = _("The request returned a 413 Request Entity Too Large. This " "generally means that rate limiting or a quota threshold was " @@ -140,6 +147,7 @@ class ServiceUnavailable(OpenstackException): else None) super(ServiceUnavailable, self).__init__(*args, **kwargs) + class RequestUriTooLong(OpenstackException): message = _("The URI was too long.") @@ -148,6 +156,7 @@ class ServerError(OpenstackException): message = _("The request returned 500 Internal Server Error" "\n\nThe response body:\n%(body)s") + class MaxRedirectsExceeded(OpenstackException): message = _("Maximum redirects (%(redirects)s) was exceeded.") @@ -165,11 +174,15 @@ class RegionAmbiguity(OpenstackException): "generally means that a region is required and you have not " "supplied one.") + class UserParameterMissing(OpenstackException): message = _("The Parameter (%(key)s) was not provided.") + class InvalidTemplateAttribute(OpenstackException): - message = _("The Referenced Attribute (%(resource)s %(key)s) is incorrect.") + message = _("The Referenced Attribute (%(resource)s %(key)s)" + " is incorrect.") + class UserKeyPairMissing(OpenstackException): message = _("The Key (%(key_name)s) could not be found.") diff --git a/heat/common/utils.py b/heat/common/utils.py index d6e7eaa884..05262d653c 100644 --- a/heat/common/utils.py +++ b/heat/common/utils.py @@ -33,6 +33,7 @@ from heat.openstack.common import exception PERFECT_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" + def chunkreadable(iter, chunk_size=65536): """ Wrap a readable iterator with a reader yielding chunks of @@ -62,6 +63,7 @@ def chunkiter(fp, chunk_size=65536): def generate_uuid(): return str(uuid.uuid4()) + def gen_uuid(): return uuid.uuid4() @@ -72,6 +74,7 @@ def strtime(at=None, fmt=PERFECT_TIME_FORMAT): at = utcnow() return at.strftime(fmt) + def parse_strtime(timestr, fmt=PERFECT_TIME_FORMAT): """Turn a formatted time back into a datetime.""" return datetime.datetime.strptime(timestr, fmt) @@ -86,6 +89,7 @@ def isotime(at=None): str += ('Z' if tz == 'UTC' else tz) return str + class LoopingCallDone(Exception): """Exception to break out and stop a LoopingCall. @@ -143,4 +147,3 @@ class LoopingCall(object): def wait(self): return self.done.wait() - diff --git a/heat/db/api.py b/heat/db/api.py index b91ac892f9..3760a3c142 100644 --- a/heat/db/api.py +++ b/heat/db/api.py @@ -27,6 +27,8 @@ supported backend. ''' from heat.openstack.common import utils + + def configure(conf): global IMPL global SQL_CONNECTION @@ -35,12 +37,15 @@ def configure(conf): SQL_CONNECTION = conf.sql_connection SQL_IDLE_TIMEOUT = conf.sql_idle_timeout + def raw_template_get(context, template_id): return IMPL.raw_template_get(context, template_id) + def raw_template_get_all(context): return IMPL.raw_template_get_all(context) + def raw_template_create(context, values): return IMPL.raw_template_create(context, values) @@ -48,9 +53,11 @@ def raw_template_create(context, values): def parsed_template_get(context, template_id): return IMPL.parsed_template_get(context, template_id) + def parsed_template_get_all(context): return IMPL.parsed_template_get_all(context) + def parsed_template_create(context, values): return IMPL.parsed_template_create(context, values) @@ -58,38 +65,51 @@ def parsed_template_create(context, values): def resource_get(context, resource_id): return IMPL.resource_get(context, resource_id) + def resource_get_all(context): return IMPL.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) + 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) + def stack_get_all(context): return IMPL.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) + def event_get_all(context): return IMPL.event_get_all(context) + def event_get_all_by_stack(context, stack_id): return IMPL.event_get_all_by_stack(context, stack_id) + def event_create(context, values): return IMPL.event_create(context, values) diff --git a/heat/db/sqlalchemy/api.py b/heat/db/sqlalchemy/api.py index a1f377de13..a1334f1d16 100644 --- a/heat/db/sqlalchemy/api.py +++ b/heat/db/sqlalchemy/api.py @@ -19,8 +19,9 @@ from sqlalchemy.orm.session import Session from heat.db.sqlalchemy import models from heat.db.sqlalchemy.session import get_session + def model_query(context, *args, **kwargs): - """ + """ :param session: if present, the session to use """ session = kwargs.get('session') or get_session() @@ -29,6 +30,7 @@ def model_query(context, *args, **kwargs): return query + def raw_template_get(context, template_id): result = model_query(context, models.RawTemplate).\ filter_by(id=template_id).first() @@ -38,20 +40,23 @@ def raw_template_get(context, template_id): return result + def raw_template_get_all(context): results = model_query(context, models.RawTemplate).all() if not results: raise Exception('no raw templates were found') - + return results + def raw_template_create(context, values): raw_template_ref = models.RawTemplate() raw_template_ref.update(values) raw_template_ref.save() return raw_template_ref + def parsed_template_get(context, template_id): result = model_query(context, models.ParsedTemplate).\ filter_by(id=template_id).first() @@ -61,20 +66,23 @@ def parsed_template_get(context, template_id): return result + def parsed_template_get_all(context): results = model_query(context, models.ParsedTemplate).all() if not results: raise Exception('no parsed templates were found') - + return results + def parsed_template_create(context, values): parsed_template_ref = models.ParsedTemplate() parsed_template_ref.update(values) parsed_template_ref.save() return parsed_template_ref + def resource_get(context, resource_id): result = model_query(context, models.Resource).\ filter_by(id=resource_id).first() @@ -84,6 +92,7 @@ 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).\ @@ -91,44 +100,51 @@ def resource_get_by_name_and_stack(context, resource_name, stack_id): return result + def resource_get_all(context): results = model_query(context, models.Resource).all() if not results: raise Exception('no resources were found') - + return results + def resource_create(context, values): resource_ref = models.Resource() resource_ref.update(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() return result + def stack_get_all(context): results = model_query(context, models.Stack).all() return results + def stack_create(context, values): stack_ref = models.Stack() 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: @@ -145,23 +161,27 @@ def stack_delete(context, stack_name): session.delete(s) session.flush() + def event_get(context, event_id): result = model_query(context, models.Event).\ filter_by(id=event_id).first() return result + def event_get_all(context): results = model_query(context, models.Event).all() return results + def event_get_all_by_stack(context, stack_id): results = model_query(context, models.Event).\ filter_by(stack_id=stack_id).all() return results + def event_create(context, values): event_ref = models.Event() event_ref.update(values) diff --git a/heat/db/sqlalchemy/manage.py b/heat/db/sqlalchemy/manage.py index 0382d72786..489f24e9fa 100644 --- a/heat/db/sqlalchemy/manage.py +++ b/heat/db/sqlalchemy/manage.py @@ -2,4 +2,5 @@ from migrate.versioning.shell import main if __name__ == '__main__': - main(url='mysql://heat:heat@localhost/heat', debug='False', repository='migrate_repo') + main(url='mysql://heat:heat@localhost/heat', debug='False', + repository='migrate_repo') diff --git a/heat/db/sqlalchemy/migrate_repo/versions/001_norwhal.py b/heat/db/sqlalchemy/migrate_repo/versions/001_norwhal.py index ba90c43de7..fc2c13373f 100644 --- a/heat/db/sqlalchemy/migrate_repo/versions/001_norwhal.py +++ b/heat/db/sqlalchemy/migrate_repo/versions/001_norwhal.py @@ -1,6 +1,7 @@ from sqlalchemy import * from migrate import * + def upgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine @@ -21,7 +22,8 @@ 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), + Column('raw_template_id', Integer, ForeignKey("raw_template.id"), + nullable=False), ) event = Table( @@ -49,13 +51,14 @@ def upgrade(migrate_engine): Column('updated_at', DateTime(timezone=False)), Column('state', String(length=255, convert_unicode=False, assert_unicode=None, - unicode_error=None, + unicode_error=None, _warn_on_bytestring=False)), Column('state_description', String(length=255, convert_unicode=False, assert_unicode=None, - unicode_error=None, + unicode_error=None, _warn_on_bytestring=False)), - Column('parsed_template_id', Integer, ForeignKey("parsed_template.id"), nullable=True), + Column('parsed_template_id', Integer, ForeignKey("parsed_template.id"), + nullable=True), Column('stack_id', Integer, ForeignKey("stack.id"), nullable=False), Column('depends_on', Integer), ) @@ -63,18 +66,20 @@ def upgrade(migrate_engine): parsedtemplate = Table( 'parsed_template', meta, Column('id', Integer, primary_key=True), - Column('raw_template_id', Integer, ForeignKey("raw_template.id"), nullable=False), + Column('raw_template_id', Integer, ForeignKey("raw_template.id"), + nullable=False), Column('template', Text()), ) tables = [rawtemplate, stack, event, parsedtemplate, resource] for table in tables: - try: + try: table.create() except Exception: meta.drop_all(tables=tables) raise + def downgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine diff --git a/heat/db/sqlalchemy/models.py b/heat/db/sqlalchemy/models.py index ea8d80a48a..5dea6f6102 100644 --- a/heat/db/sqlalchemy/models.py +++ b/heat/db/sqlalchemy/models.py @@ -27,8 +27,9 @@ from heat.db.sqlalchemy.session import get_session BASE = declarative_base() + class Json(types.TypeDecorator, types.MutableType): - impl=types.Text + impl = types.Text def process_bind_param(self, value, dialect): return dumps(value) @@ -36,6 +37,7 @@ class Json(types.TypeDecorator, types.MutableType): def process_result_value(self, value, dialect): return loads(value) + class HeatBase(object): """Base class for Heat Models.""" __table_args__ = {'mysql_engine': 'InnoDB'} @@ -94,6 +96,7 @@ class HeatBase(object): local.update(joined) return local.iteritems() + class RawTemplate(BASE, HeatBase): """Represents an unparsed template which should be in JSON format.""" @@ -101,17 +104,21 @@ class RawTemplate(BASE, HeatBase): id = Column(Integer, primary_key=True) template = Column(Json) parsed_template = relationship("ParsedTemplate",\ - uselist=False, backref="raw_template", cascade="all, delete", passive_deletes=True) + 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) + id = Column(Integer, primary_key=True) 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.""" @@ -124,6 +131,7 @@ class Stack(BASE, HeatBase): 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.""" @@ -134,9 +142,10 @@ class Event(BASE, HeatBase): nullable=False) stack = relationship(Stack, backref=backref('events'), cascade="all, delete", passive_deletes=True) - + name = Column(String) - + + class Resource(BASE, HeatBase): """Represents a resource created by the heat engine.""" @@ -149,11 +158,12 @@ class Resource(BASE, HeatBase): state_description = Column('state_description', String) parsed_template_id = Column(Integer, ForeignKey('parsed_template.id'),\ nullable=True) - parsed_template = relationship(ParsedTemplate, + 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) + stack = relationship(Stack, backref=backref('resources'), + cascade="all, delete", passive_deletes=True) depends_on = Column(Integer) diff --git a/heat/db/sqlalchemy/session.py b/heat/db/sqlalchemy/session.py index 596c78592f..572271117d 100644 --- a/heat/db/sqlalchemy/session.py +++ b/heat/db/sqlalchemy/session.py @@ -90,8 +90,10 @@ def get_maker(engine, autocommit=True, expire_on_commit=False): autocommit=autocommit, expire_on_commit=expire_on_commit) + def _get_sql_connection(): return db_api.SQL_CONNECTION + def _get_sql_idle_timeout(): return db_api.SQL_IDLE_TIMEOUT diff --git a/heat/engine/__init__.py b/heat/engine/__init__.py index 1d3b347970..1f19be5756 100644 --- a/heat/engine/__init__.py +++ b/heat/engine/__init__.py @@ -1,2 +1 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 - diff --git a/heat/engine/manager.py b/heat/engine/manager.py index 88efdd22e6..6a0e157935 100644 --- a/heat/engine/manager.py +++ b/heat/engine/manager.py @@ -29,6 +29,7 @@ from heat.engine import parser from heat.db import api as db_api logger = logging.getLogger('heat.engine.manager') + class EngineManager(manager.Manager): """ Manages the running instances from creation to destruction. @@ -52,7 +53,7 @@ class EngineManager(manager.Manager): arg2 -> Dict of http request parameters passed in from API side. """ logger.info('context is %s' % context) - res = {'stacks': [] } + res = {'stacks': []} stacks = db_api.stack_get_all(None) if stacks == None: return res @@ -62,7 +63,8 @@ class EngineManager(manager.Manager): mem['stack_id'] = s.id mem['stack_name'] = s.name mem['created_at'] = str(s.created_at) - mem['template_description'] = ps.t.get('Description', 'No description') + mem['template_description'] = ps.t.get('Description', + 'No description') mem['stack_status'] = ps.t.get('StackStatus', 'unknown') res['stacks'].append(mem) @@ -75,7 +77,7 @@ class EngineManager(manager.Manager): arg2 -> Name of the stack you want to see. arg3 -> Dict of http request parameters passed in from API side. """ - res = {'stacks': [] } + res = {'stacks': []} s = db_api.stack_get(None, stack_name) if s: ps = parser.Stack(s.name, s.raw_template.template, params) @@ -89,7 +91,8 @@ class EngineManager(manager.Manager): mem['Parameters'] = ps.t['Parameters'] mem['StackStatusReason'] = 'TODO' mem['TimeoutInMinutes'] = 'TODO' - mem['TemplateDescription'] = ps.t.get('Description', 'No description') + mem['TemplateDescription'] = ps.t.get('Description', + 'No description') mem['StackStatus'] = ps.t.get('StackStatus', 'unknown') res['stacks'].append(mem) @@ -97,7 +100,8 @@ class EngineManager(manager.Manager): def create_stack(self, context, stack_name, template, params): """ - The create_stack method creates a new stack using the template provided. + The create_stack method creates a new stack using the template + provided. Note that at this stage the template has already been fetched from the heat-api process if using a template-url. arg1 -> RPC context. diff --git a/heat/engine/parser.py b/heat/engine/parser.py index 08869255e9..eac2a90b2b 100644 --- a/heat/engine/parser.py +++ b/heat/engine/parser.py @@ -23,30 +23,25 @@ from heat.db import api as db_api logger = logging.getLogger('heat.engine.parser') + class Stack(object): def __init__(self, stack_name, template, parms=None): self.id = 0 self.t = template - if self.t.has_key('Parameters'): - self.parms = self.t['Parameters'] - else: - self.parms = {} - if self.t.has_key('Mappings'): - self.maps = self.t['Mappings'] - else: - self.maps = {} - if self.t.has_key('Outputs'): - self.outputs = self.t['Outputs'] - else: - self.outputs = {} - + self.parms = self.t.get('Parameters', {}) + self.maps = self.t.get('Mappings', {}) + self.outputs = self.t.get('Outputs', {}) 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." } + + 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." } if parms != None: self._apply_user_parameters(parms) @@ -63,19 +58,26 @@ class Stack(object): for r in self.t['Resources']: type = self.t['Resources'][r]['Type'] if type == 'AWS::EC2::Instance': - self.resources[r] = resources.Instance(r, self.t['Resources'][r], self) + self.resources[r] = resources.Instance(r, + self.t['Resources'][r], self) elif type == 'AWS::EC2::Volume': - self.resources[r] = resources.Volume(r, self.t['Resources'][r], self) + self.resources[r] = resources.Volume(r, + self.t['Resources'][r], self) elif type == 'AWS::EC2::VolumeAttachment': - self.resources[r] = resources.VolumeAttachment(r, self.t['Resources'][r], self) + self.resources[r] = resources.VolumeAttachment(r, + self.t['Resources'][r], self) elif type == 'AWS::EC2::EIP': - self.resources[r] = resources.ElasticIp(r, self.t['Resources'][r], self) + self.resources[r] = resources.ElasticIp(r, + self.t['Resources'][r], self) elif type == 'AWS::EC2::EIPAssociation': - self.resources[r] = resources.ElasticIpAssociation(r, self.t['Resources'][r], self) + self.resources[r] = resources.ElasticIpAssociation(r, + self.t['Resources'][r], self) elif type == 'AWS::EC2::SecurityGroup': - self.resources[r] = resources.SecurityGroup(r, self.t['Resources'][r], self) + self.resources[r] = resources.SecurityGroup(r, + self.t['Resources'][r], self) else: - self.resources[r] = resources.GenericResource(r, self.t['Resources'][r], self) + self.resources[r] = resources.GenericResource(r, + self.t['Resources'][r], self) self.calulate_dependencies(self.t['Resources'][r], self.resources[r]) @@ -96,14 +98,8 @@ class Stack(object): res = jp['member'] res['NoEcho'] = 'false' res['ParameterKey'] = p - if self.parms[p].has_key('Description'): - res['Description'] = self.parms[p]['Description'] - else: - res['Description'] = '' - if self.parms[p].has_key('Default'): - res['DefaultValue'] = self.parms[p]['Default'] - else: - res['DefaultValue'] = '' + res['Description'] = self.parms[p].get('Description', '') + res['DefaultValue'] = self.parms[p].get('Default', '') response['ValidateTemplateResult']['Parameters'].append(res) return response @@ -185,15 +181,10 @@ class Stack(object): outs = [] for o in self.outputs: out = {} - if self.outputs[o].has_key('Description'): - out['Description'] = self.outputs[o]['Description'] - else: - out['Description'] = 'No description given' + out['Description'] = self.outputs[o].get('Description', + 'No description given') out['OutputKey'] = o - if self.outputs[o].has_key('Value'): - out['OutputValue'] = self.outputs[o]['Value'] - else: - out['OutputValue'] = '' + out['OutputValue'] = self.outputs[o].get('Value', '') outs.append(out) return outs @@ -220,7 +211,7 @@ class Stack(object): def _apply_user_parameter(self, key, value): logger.debug('appling user parameter %s=%s ' % (key, value)) - if not self.parms.has_key(key): + if not key in self.parms: self.parms[key] = {} self.parms[key]['Value'] = value @@ -231,16 +222,17 @@ class Stack(object): try: key_name = 'Parameters.member.%s.ParameterKey' % s[2] value_name = 'Parameters.member.%s.ParameterValue' % s[2] - self._apply_user_parameter(parms[key_name], parms[value_name]) + self._apply_user_parameter(parms[key_name], + parms[value_name]) except Exception: logger.error('Could not apply parameter %s' % p) def parameter_get(self, key): if self.parms[key] == None: raise exception.UserParameterMissing(key=key) - elif self.parms[key].has_key('Value'): + elif 'Value' in self.parms[key]: return self.parms[key]['Value'] - elif self.parms[key].has_key('Default'): + elif 'Default' in self.parms[key]: return self.parms[key]['Default'] else: raise exception.UserParameterMissing(key=key) @@ -253,7 +245,7 @@ class Stack(object): for i in s: if i == 'Ref' and \ isinstance(s[i], (basestring, unicode)) and \ - self.parms.has_key(s[i]): + s[i] in self.parms: return self.parameter_get(s[i]) else: s[i] = self.resolve_static_refs(s[i]) @@ -298,7 +290,7 @@ class Stack(object): ''' if isinstance(s, dict): for i in s: - if i == 'Ref' and self.resources.has_key(s[i]): + if i == 'Ref' and s[i] in self.resources: return self.resources[s[i]].FnGetRefId() elif i == 'Fn::GetAtt': resource_name = s[i][0] @@ -351,5 +343,3 @@ class Stack(object): for index, item in enumerate(s): s[index] = self.resolve_base64(item) return s - - diff --git a/heat/engine/resources.py b/heat/engine/resources.py index 303d331d99..e17966643d 100644 --- a/heat/engine/resources.py +++ b/heat/engine/resources.py @@ -49,6 +49,7 @@ else: cloudinit_path = '%s/heat/%s/' % (p, "cloudinit") break + class Resource(object): CREATE_IN_PROGRESS = 'CREATE_IN_PROGRESS' CREATE_FAILED = 'CREATE_FAILED' @@ -77,7 +78,7 @@ class Resource(object): self.id = None self._nova = {} - if not self.t.has_key('Properties'): + if not 'Properties' in self.t: # make a dummy entry to prevent having to check all over the # place for it. self.t['Properties'] = {} @@ -86,7 +87,7 @@ class Resource(object): stack.resolve_find_in_map(self.t) def nova(self, service_type='compute'): - if self._nova.has_key(service_type): + if service_type in self._nova: return self._nova[service_type] username = self.stack.creds['username'] @@ -98,9 +99,10 @@ class Resource(object): else: service_name = None - - self._nova[service_type] = client.Client(username, password, tenant, auth_url, - service_type=service_type, service_name=service_name) + self._nova[service_type] = client.Client(username, password, tenant, + auth_url, + service_type=service_type, + service_name=service_name) return self._nova[service_type] def create(self): @@ -146,8 +148,10 @@ class Resource(object): self.state = new_state def delete(self): - print 'deleting %s name:%s inst:%s db_id:%s' % (self.t['Type'], self.name, - self.instance_id, str(self.id)) + print 'deleting %s name:%s inst:%s db_id:%s' % (self.t['Type'], + self.name, + self.instance_id, + str(self.id)) def reload(self): pass @@ -173,6 +177,7 @@ http://docs.amazonwebservices.com/AWSCloudFormation/latest/UserGuide/intrinsic-f ''' return base64.b64encode(data) + class GenericResource(Resource): def __init__(self, name, json_snippet, stack): super(GenericResource, self).__init__(name, json_snippet, stack) @@ -185,13 +190,14 @@ class GenericResource(Resource): print 'creating GenericResource %s' % self.name self.state_set(self.CREATE_COMPLETE) + class SecurityGroup(Resource): def __init__(self, name, json_snippet, stack): super(SecurityGroup, self).__init__(name, json_snippet, stack) self.instance_id = '' - if self.t['Properties'].has_key('GroupDescription'): + if 'GroupDescription' in self.t['Properties']: self.description = self.t['Properties']['GroupDescription'] else: self.description = '' @@ -205,7 +211,7 @@ class SecurityGroup(Resource): sec = self.nova().security_groups.create(self.name, self.description) self.instance_id_set(sec.id) - if self.t['Properties'].has_key('SecurityGroupIngress'): + if 'SecurityGroupIngress' in self.t['Properties']: for i in self.t['Properties']['SecurityGroupIngress']: rule = self.nova().security_group_rules.create(sec.id, i['IpProtocol'], @@ -215,7 +221,8 @@ class SecurityGroup(Resource): self.state_set(self.CREATE_COMPLETE) def delete(self): - if self.state == self.DELETE_IN_PROGRESS or self.state == self.DELETE_COMPLETE: + if self.state == self.DELETE_IN_PROGRESS or \ + self.state == self.DELETE_COMPLETE: return self.state_set(self.DELETE_IN_PROGRESS) @@ -235,13 +242,14 @@ class SecurityGroup(Resource): def FnGetRefId(self): return unicode(self.name) + class ElasticIp(Resource): def __init__(self, name, json_snippet, stack): super(ElasticIp, self).__init__(name, json_snippet, stack) self.instance_id = '' self.ipaddress = '' - if self.t.has_key('Properties') and self.t['Properties'].has_key('Domain'): + if 'Domain' in self.t['Properties']: logger.warn('*** can\'t support Domain %s yet' % (self.t['Properties']['Domain'])) def create(self): @@ -259,7 +267,8 @@ class ElasticIp(Resource): def delete(self): """De-allocate a floating IP.""" - if self.state == self.DELETE_IN_PROGRESS or self.state == self.DELETE_COMPLETE: + if self.state == self.DELETE_IN_PROGRESS or \ + self.state == self.DELETE_COMPLETE: return self.state_set(self.DELETE_IN_PROGRESS) @@ -279,12 +288,13 @@ class ElasticIp(Resource): else: raise exception.InvalidTemplateAttribute(resource=self.name, key=key) + class ElasticIpAssociation(Resource): def __init__(self, name, json_snippet, stack): super(ElasticIpAssociation, self).__init__(name, json_snippet, stack) def FnGetRefId(self): - if not self.t['Properties'].has_key('EIP'): + if not 'EIP' in self.t['Properties']: return unicode('0.0.0.0') else: return unicode(self.t['Properties']['EIP']) @@ -306,7 +316,8 @@ class ElasticIpAssociation(Resource): def delete(self): """Remove a floating IP address from a server.""" - if self.state == self.DELETE_IN_PROGRESS or self.state == self.DELETE_COMPLETE: + if self.state == self.DELETE_IN_PROGRESS or \ + self.state == self.DELETE_COMPLETE: return self.state_set(self.DELETE_IN_PROGRESS) @@ -342,7 +353,8 @@ class Volume(Resource): self.state_set(self.CREATE_FAILED) def delete(self): - if self.state == self.DELETE_IN_PROGRESS or self.state == self.DELETE_COMPLETE: + if self.state == self.DELETE_IN_PROGRESS or \ + self.state == self.DELETE_COMPLETE: return if self.instance_id != None: @@ -358,6 +370,7 @@ class Volume(Resource): self.nova('volume').volumes.delete(self.instance_id) self.state_set(self.DELETE_COMPLETE) + class VolumeAttachment(Resource): def __init__(self, name, json_snippet, stack): super(VolumeAttachment, self).__init__(name, json_snippet, stack) @@ -369,9 +382,10 @@ class VolumeAttachment(Resource): self.state_set(self.CREATE_IN_PROGRESS) super(VolumeAttachment, self).create() - print 'Attaching InstanceId %s VolumeId %s Device %s' % (self.t['Properties']['InstanceId'], - self.t['Properties']['VolumeId'], - self.t['Properties']['Device']) + print 'Attaching InstanceId %s VolumeId %s Device %s' % \ + (self.t['Properties']['InstanceId'], + self.t['Properties']['VolumeId'], + self.t['Properties']['Device']) va = self.nova().volumes.create_server_volume(server_id=self.t['Properties']['InstanceId'], volume_id=self.t['Properties']['VolumeId'], device=self.t['Properties']['Device']) @@ -387,7 +401,8 @@ class VolumeAttachment(Resource): self.state_set(self.CREATE_FAILED) def delete(self): - if self.state == self.DELETE_IN_PROGRESS or self.state == self.DELETE_COMPLETE: + if self.state == self.DELETE_IN_PROGRESS or \ + self.state == self.DELETE_COMPLETE: return self.state_set(self.DELETE_IN_PROGRESS) Resource.delete(self) @@ -411,19 +426,20 @@ class VolumeAttachment(Resource): self.state_set(self.DELETE_COMPLETE) + class Instance(Resource): def __init__(self, name, json_snippet, stack): super(Instance, self).__init__(name, json_snippet, stack) self.ipaddress = '0.0.0.0' - if not self.t['Properties'].has_key('AvailabilityZone'): + if not 'AvailabilityZone' in self.t['Properties']: self.t['Properties']['AvailabilityZone'] = 'nova' self.itype_oflavor = {'t1.micro': 'm1.tiny', 'm1.small': 'm1.small', 'm1.medium': 'm1.medium', 'm1.large': 'm1.large', - 'm1.xlarge': 'm1.tiny', # TODO(sdake) + 'm1.xlarge': 'm1.tiny', # TODO(sdake) 'm2.xlarge': 'm1.xlarge', 'm2.2xlarge': 'm1.large', 'm2.4xlarge': 'm1.large', @@ -432,7 +448,6 @@ class Instance(Resource): 'cc2.8xlarge': 'm1.large', 'cg1.4xlarge': 'm1.large'} - def FnGetAtt(self, key): res = None @@ -461,11 +476,11 @@ class Instance(Resource): Resource.create(self) props = self.t['Properties'] - if not props.has_key('KeyName'): + if not 'KeyName' in props: raise exception.UserParameterMissing(key='KeyName') - if not props.has_key('InstanceType'): + if not 'InstanceType' in props: raise exception.UserParameterMissing(key='InstanceType') - if not props.has_key('ImageId'): + if not 'ImageId' in props: raise exception.UserParameterMissing(key='ImageId') userdata = self.t['Properties']['UserData'] @@ -505,17 +520,21 @@ class Instance(Resource): fp = open('%s/%s' % (cloudinit_path, 'config'), 'r') msg = MIMEText(fp.read(), _subtype='cloud-config') fp.close() - msg.add_header('Content-Disposition', 'attachment', filename='cloud-config') + msg.add_header('Content-Disposition', 'attachment', + filename='cloud-config') mime_blob.attach(msg) fp = open('%s/%s' % (cloudinit_path, 'part-handler.py'), 'r') msg = MIMEText(fp.read(), _subtype='part-handler') fp.close() - msg.add_header('Content-Disposition', 'attachment', filename='part-handler.py') + msg.add_header('Content-Disposition', 'attachment', + filename='part-handler.py') mime_blob.attach(msg) - msg = MIMEText(json.dumps(self.t['Metadata']), _subtype='x-cfninitdata') - msg.add_header('Content-Disposition', 'attachment', filename='cfn-init-data') + msg = MIMEText(json.dumps(self.t['Metadata']), + _subtype='x-cfninitdata') + msg.add_header('Content-Disposition', 'attachment', + filename='cfn-init-data') mime_blob.attach(msg) msg = MIMEText(userdata, _subtype='x-shellscript') @@ -539,7 +558,8 @@ 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: + if self.state == self.DELETE_IN_PROGRESS or \ + self.state == self.DELETE_COMPLETE: return self.state_set(self.DELETE_IN_PROGRESS) Resource.delete(self) diff --git a/heat/manager.py b/heat/manager.py index 3921281841..8940fdc630 100644 --- a/heat/manager.py +++ b/heat/manager.py @@ -171,5 +171,3 @@ class Manager(object): for key in FLAGS: config[key] = FLAGS.get(key, None) return config - - diff --git a/heat/rpc/__init__.py b/heat/rpc/__init__.py index a352b34f30..b10e3f1477 100644 --- a/heat/rpc/__init__.py +++ b/heat/rpc/__init__.py @@ -184,12 +184,14 @@ def fanout_cast_to_server(context, server_params, topic, msg): _RPCIMPL = None + def configure(conf): """Delay import of rpc_backend until FLAGS are loaded.""" print 'configuring rpc %s' % conf.rpc_backend global _RPCIMPL _RPCIMPL = utils.import_object(conf.rpc_backend) + def _get_impl(): """Delay import of rpc_backend until FLAGS are loaded.""" global _RPCIMPL @@ -197,4 +199,3 @@ def _get_impl(): print 'rpc not configured' return _RPCIMPL - diff --git a/heat/rpc/impl_qpid.py b/heat/rpc/impl_qpid.py index 9d83c95005..7c492c681f 100644 --- a/heat/rpc/impl_qpid.py +++ b/heat/rpc/impl_qpid.py @@ -33,6 +33,7 @@ from heat.rpc import common as rpc_common LOG = logging.getLogger(__name__) + class ConsumerBase(object): """Consumer base class.""" @@ -199,7 +200,7 @@ class TopicPublisher(Publisher): """init a 'topic' publisher. """ super(TopicPublisher, self).__init__(session, - "%s/%s" % (config.FLAGS.control_exchange, topic)) + "%s/%s" % (config.FLAGS.control_exchange, topic)) class FanoutPublisher(Publisher): @@ -217,7 +218,7 @@ class NotifyPublisher(Publisher): """init a 'topic' publisher. """ super(NotifyPublisher, self).__init__(session, - "%s/%s" % (config.FLAGS.control_exchange, topic), + "%s/%s" % (config.FLAGS.control_exchange, topic), {"durable": True}) diff --git a/heat/service.py b/heat/service.py index 126045ab39..db6a4f6065 100644 --- a/heat/service.py +++ b/heat/service.py @@ -38,8 +38,11 @@ from heat import version LOG = logging.getLogger(__name__) + class Launcher(object): - """Launch one or more services and wait for them to complete.""" + """ + Launch one or more services and wait for them to complete. + """ def __init__(self): """Initialize the service launcher. diff --git a/heat/tests/examples/test1.py b/heat/tests/examples/test1.py index f08f81fccd..0fc8d6c168 100644 --- a/heat/tests/examples/test1.py +++ b/heat/tests/examples/test1.py @@ -10,12 +10,16 @@ from nose.plugins.attrib import attr from nose import with_setup # module level + + def setUp(): print "test1 setup complete" + def tearDown(): print "test1 teardown complete" + @with_setup(setUp, tearDown) # test level @attr(tag=['example', 'func']) @attr(speed='fast') @@ -23,6 +27,7 @@ def test_a(): assert 'a' == 'a' print "assert a" + def test_b(): assert 'b' == 'b' print "assert b" diff --git a/heat/tests/examples/test2.py b/heat/tests/examples/test2.py index 9c3ec2cebb..1f1325dec8 100644 --- a/heat/tests/examples/test2.py +++ b/heat/tests/examples/test2.py @@ -9,14 +9,18 @@ import nose from nose.plugins.attrib import attr # sets attribute on all test methods + + @attr(tag=['example', 'class']) @attr(speed='fast') class TestClass: def test2(self): assert 'b' == 'b' print "assert b" + def setUp(self): print "test2 setup complete" + def tearDown(self): print "test2 teardown complete" diff --git a/heat/tests/examples/test3.py b/heat/tests/examples/test3.py index 4e2ddfbabd..77191406d7 100644 --- a/heat/tests/examples/test3.py +++ b/heat/tests/examples/test3.py @@ -9,13 +9,17 @@ import unittest from nose.plugins.attrib import attr # sets attribute on all test methods + + @attr(tag=['example', 'unittest']) @attr(speed='fast') class ExampleTest(unittest.TestCase): def test_a(self): self.assert_(1 == 1) + def setUp(self): print "test3 setup complete" + def tearDown(self): print "test3 teardown complete"