From fdfb967cef058cad934abc3c11d7f3785b540903 Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Thu, 31 May 2012 11:17:30 +0200 Subject: [PATCH] Refactor Resource creation Allow the Resource class to instantiate the correct type of object for each resource. Change-Id: I518f27fa27f675b9e497aac40962331833077aed Signed-off-by: Zane Bitter --- heat/engine/parser.py | 37 ++++-------------------- heat/engine/resource_types.py | 53 +++++++++++++++++++++++++++++++++++ heat/engine/resources.py | 12 ++++++++ 3 files changed, 70 insertions(+), 32 deletions(-) create mode 100644 heat/engine/resource_types.py diff --git a/heat/engine/parser.py b/heat/engine/parser.py index fb2754962d..70020d6ed0 100644 --- a/heat/engine/parser.py +++ b/heat/engine/parser.py @@ -18,38 +18,12 @@ import json import logging from heat.common import exception from heat.engine import checkeddict -from heat.engine import cloud_watch -from heat.engine import eip -from heat.engine import escalation_policy -from heat.engine import instance -from heat.engine import resources -from heat.engine import security_group -from heat.engine import user -from heat.engine import volume -from heat.engine import wait_condition +from heat.engine.resources import Resource from heat.db import api as db_api logger = logging.getLogger(__file__) -(RESOURCE_CLASSES,) = ({ - 'AWS::EC2::Instance': instance.Instance, - 'AWS::EC2::Volume': volume.Volume, - 'AWS::EC2::VolumeAttachment': volume.VolumeAttachment, - 'AWS::EC2::EIP': eip.ElasticIp, - 'AWS::EC2::EIPAssociation': eip.ElasticIpAssociation, - 'AWS::EC2::SecurityGroup': security_group.SecurityGroup, - 'AWS::CloudWatch::Alarm': cloud_watch.CloudWatchAlarm, - 'HEAT::Recovery::EscalationPolicy': escalation_policy.EscalationPolicy, - 'AWS::CloudFormation::WaitConditionHandle': - wait_condition.WaitConditionHandle, - 'AWS::CloudFormation::WaitCondition': wait_condition.WaitCondition, - 'AWS::IAM::User': user.User, - 'AWS::IAM::AccessKey': user.AccessKey, - 'HEAT::HA::Restarter': instance.Restarter, -},) - - class Stack(object): IN_PROGRESS = 'IN_PROGRESS' CREATE_FAILED = 'CREATE_FAILED' @@ -94,12 +68,11 @@ class Stack(object): self._apply_user_parameters(parms) self.resources = {} - for rname, res in self.t['Resources'].items(): - ResourceClass = RESOURCE_CLASSES.get(res['Type'], - resources.GenericResource) - self.resources[rname] = ResourceClass(rname, res, self) + for rname, rdesc in self.t['Resources'].items(): + res = Resource(rname, rdesc, self) + self.resources[rname] = res - self.calulate_dependencies(res, self.resources[rname]) + self.calulate_dependencies(rdesc, res) def validate(self): ''' diff --git a/heat/engine/resource_types.py b/heat/engine/resource_types.py new file mode 100644 index 0000000000..cc2fa3d948 --- /dev/null +++ b/heat/engine/resource_types.py @@ -0,0 +1,53 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# +# Licensed 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. + +""" +Register of resource types and their mapping to Resource classes. +""" + + +from heat.engine import resources + +from heat.engine import cloud_watch +from heat.engine import eip +from heat.engine import escalation_policy +from heat.engine import instance +from heat.engine import security_group +from heat.engine import user +from heat.engine import volume +from heat.engine import wait_condition + + +_resource_classes = { + 'AWS::CloudFormation::WaitCondition': wait_condition.WaitCondition, + 'AWS::CloudFormation::WaitConditionHandle': + wait_condition.WaitConditionHandle, + 'AWS::CloudWatch::Alarm': cloud_watch.CloudWatchAlarm, + 'AWS::EC2::EIP': eip.ElasticIp, + 'AWS::EC2::EIPAssociation': eip.ElasticIpAssociation, + 'AWS::EC2::Instance': instance.Instance, + 'AWS::EC2::SecurityGroup': security_group.SecurityGroup, + 'AWS::EC2::Volume': volume.Volume, + 'AWS::EC2::VolumeAttachment': volume.VolumeAttachment, + 'AWS::IAM::User': user.User, + 'AWS::IAM::AccessKey': user.AccessKey, + 'HEAT::HA::Restarter': instance.Restarter, + 'HEAT::Recovery::EscalationPolicy': escalation_policy.EscalationPolicy, +} + + +def getClass(resource_type): + """Return the appropriate Resource class for the resource type.""" + return _resource_classes.get(resource_type, resources.GenericResource) diff --git a/heat/engine/resources.py b/heat/engine/resources.py index 8fe36e9332..5e66ff5ccd 100644 --- a/heat/engine/resources.py +++ b/heat/engine/resources.py @@ -40,6 +40,18 @@ class Resource(object): UPDATE_FAILED = 'UPDATE_FAILED' UPDATE_COMPLETE = 'UPDATE_COMPLETE' + def __new__(cls, name, json, stack): + '''Create a new Resource of the appropriate class for its type.''' + + if cls != Resource: + # Call is already for a subclass, so pass it through + return super(Resource, cls).__new__(cls, name, json, stack) + + # Select the correct subclass to instantiate + import resource_types + ResourceClass = resource_types.getClass(json['Type']) + return ResourceClass(name, json, stack) + def __init__(self, name, json_snippet, stack): self.t = json_snippet self.depends_on = []