[openstack-dev] [Heat] A concrete proposal for Heat Providers

Angus Salkeld asalkeld at redhat.com
Fri Apr 26 01:35:36 UTC 2013

On 25/04/13 21:35 +0200, Zane Bitter wrote:
>Greetings Heaters,
>I'm hearing a lot about (and struggling to keep track of) multiple 
>people working on competing proposals for how a Heat template 
>language should look if we designed it from scratch and, while that's 
>valuable in helping to figure out the primitives we need, I'd also 
>like to approach it from the other direction and start figuring out 
>what path we need to get on to bring the new feature direction that 
>our users want to fruition. We all agreed at the Summit that we need 
>to pursue these new features in an incremental manner, and we should 
>not forget *why*:
>   A complex system that works is invariably found to have evolved
>   from a simple system that worked.
>                     -- http://en.wikipedia.org/wiki/Gall's_law
>What follows is a concrete proposal for how we could implement one of 
>the requested features, starting from use cases, through the 
>predicted code changes required and looping back around to user 
>benefits. It certainly does not purport to implement every feature 
>requested by users. It is likely wrong in the particulars, certainly 
>in ways that will not be discovered at least until we have 
>implemented it. But it is a concrete proposal. It begins with an 
>excellent summary of the use case from Adrian...
>On 13/04/13 00:36, Adrian Otto wrote:
>> Goal: Deploy my app on my chosen OpenStack based public cloud, 
>using Heat for Dev/Test. For Production, deploy to my private 
>OpenStack cloud.
>> Scenario: My app depends on a MySQL database. My public cloud 
>provider has a hosted "mysql" service that is offered through a 
>Provider plug-in. It's there automatically because my cloud hosting 
>company put it there.  I deploy, and finish my testing on the public 
>cloud. I want to go to production now.
>> Solution: The Provider gives you a way to abstract the different 
>cloud implementations. I establish an equivalent Provider on my 
>private OpenStack cloud using RedDwarf. I set up a Provider that 
>offers "mysql" in my private cloud. Now the same setup works on both 
>clouds, even though the API for my local "mysql" service may actually 
>differ from the database provisioning API in the public cloud. Now I 
>deploy on my "production" Environment in my private cloud, and it 
>So, the first and most important thing to note is that this is 
>exactly how Heat works _now_.
>There is a resource type called AWS::RDS::DBInstance and the operator 
>of your cloud can choose a plugin to implement that interface. The 
>plugin shipping with Heat actually just spins up a somewhat hacky 
>Heat stack running MySQL... in future we hope to ship a RedDwarf Lite 
>plugin, and of course any cloud provider with their own DBaaS could 
>easily write a plugin to interface with that. (Note that when we do 
>see a RedDwarf Lite plugin we'll probably also see a variant called 
>something like OS::RedDwarf::DBInstance with more OpenStack-specific 
>properties &c.)
>So that's how Heat works today. How can we make this better? Well, 
>one thing obviously sucks: your cloud operator, and not you, gets to 
>decide which plugin is used. That sorta makes sense when it's an 
>interface to an XaaS thing in their cloud, but if it's just a Nova 
>instance running MySQL and you don't like the version your operator 
>has gone with, you are SOL. You can try running your own Heat engine, 
>but you're probably going to have to really hack at it first because 
>whenever anything in-guest has to talk back to you, the endpoint is 
>obtained from the same Keystone catalog that you're using to talk to 
>the other services. And no cloud operator in the world - not even 
>your friendly local IT department - is going to let users upload 
>Python code to run in-memory in their orchestration engine along with 
>all of the other users' code.
>If only there were some sort of language for defining OpenStack 
>services that could be safely executed by users...
>Of course that's exactly what we're all about on this project :). So 
>my proposal is to allow users to define their own resource types 
>using a Heat template. Heat would know to use this template instead 
>of a built-in type from a "Provider" member in the Resource 
>definition that contains a URL to the template. (I'm appropriating 
>the name "Provider" from Rackspace's DSL proposal for now because 
>inventing new names for things that already exist is a sucker's 
>These are the tasks that come to mind that would be required to 
>implement this (each of these bullet points could become a 
>* Create a Custom resource type that is based on a nested stack but, 
>unlike the AWS::CloudFormation::Stack type, has properties and 
>attributes inferred from the parameters and outputs (respectively) of 
>the template provided.

So this is to convert from resource properties defined in the
DBInstance to the nested stack parameters (and to make sure they
match up).

>* Allow JSON values for parameters.
>* Introduce the concept of _stack_ Metadata, and provide a way to 
>access it in a template (pseudo-parameter?).
>* Modify resource instantiation to create a Custom resource whenever 
>a resource has a non-empty "Provider" attribute.
>* Introduce a schema for attributes (i.e. allowed arguments to 
>Fn::GetAttr) [desirable anyway for autogenerating documentation]
>* Add an API to get a generic template version of any built-in 
>resource (with all properties/outputs defined) that can be easily 
>customised to make a new provider template.
>A possible avenue for increasing flexibility:
>* Add support for more template functions that manipulate the 
>template directly:
>  - Array/dictionary (uh, object) lookup
>  - more string functions?
>  - maybe conditionals?
>  - definitely NOT loops/map.
>What might all of this give us?
> + Users are no longer dependent on the operator to provide the 
>resource type they need (perhaps for cross-cloud compatibility), but 
>can supply their own.
> + Users can effectively subclass built-in types. For example, you 
>could create a Puppet Instance template that configures an instance 
>as a Puppet slave, then selectively use that in place of a regular 
>instance and just pass the metadata to specialise it.
> + Users can share their provider templates: as soon as a second 
>person is trying to configure a puppet slave in a template we're 
>wasting an opportunity - this will enable work like that to be 
> + This is infinitely flexible at the platform layer - anybody 
>(Puppet, Chef, OpenShift, &c.) can publish an Instance provider 
>How else might we improve this? Well, having to load a template from 
>a URL is definitely a limitation - albeit not a new one (the 
>AWS::CloudFormation::Stack resource type already has this 
>limitation). Perhaps we should let the user post multiple, named, 
>implementations of a resource type and reference them by name 
>(instead of URL) in the "Provider" field.
>* Modify the resource instantiation to search among multiple named 
>definitions (either Custom or Plugin) for a resource type, according 
>to the "Provider" name.
>* Add an API for posting multiple named implementations of a resource type.
> + The user can modify the default Provider for a resource if they so 
>desire (but this is tenant-wide... or perhaps that's where 
>Environments come in).
> + Provider templates can be uploaded directly to Heat instead of 
>e.g. to Swift.
> + Operators can reuse the mechanism to provide versioned Plugins 
>and/or multiple implementations of Resource types.

Nice Zane,

Just to clarify what this gives the user....

   vim ~/my_hot_nested_stacks/foo.template

   heat publish-template --private ~/my_hot_nested_stacks/foo.template --type "AWS::RDS::DBInstance" 
(returns the url to the template)

So now we have a user generated nested stack that can replace the
builtin one (and the mechanism to do the mapping).

now I just use any template that uses a "AWS::RDS::DBInstance"
resource and my nested stack is used.

So this does not need the provider except when you what if you want to control
the implementation:

   heat publish-template --private \
   https://github.com/zaneb/hot-templates/raw/master/db.templ --type "AWS::RDS::DBInstance" 

   heat template-list
   AWS::RDS::DBInstance    builtin
   AWS::RDS::DBInstance    http://..../foo.template
   AWS::RDS::DBInstance    https://github.com/zaneb/hot-templates/raw/master/db.templ 

when I create a stack I do something like the following:

   heat create teststack -f myapp.template -P "InstanceType=m1.large;KeyName=heat_key" --use "AWS::RDS::DBInstance=http://..../foo.template"

That looks messy so it might make sense to use the environment idea to
define the mapping of ResourceType to nested stack.

General question:
Do we want to support different providers of the same Resource type
within the same template? - I assume yes.

If I were to suggest baby steps:
1) have property valid on all resources "provider_url"
    prove you can start an inbuilt resource from a
    nested stack template with all the property validation goodness.
2) add "heat publish-template/list-templates/.."
3) add the environment concept to make defining the mapping more user
    friendly - this would just set the "provider_url" property on the
    resources so you don't have to edit templates or have super long
    command lines.

More crazy ideas:
what about starting a db instance as a normal stack and then
"attaching" to it? It's just a stack after all (it's just already

   heat stack-create wordpress -f wp.templ -P "..." \
   --use "AWS::RDS::DBInstance=stack-url"

This way you could reuse services (might need a refcount tho').
Any one see this as a good idea?


>So, in summary, this plan appears to provide real, identified value 
>to users; relies for the most part on existing technology in Heat 
>(nested stacks are actually pretty cool, if I may say so); includes a 
>series of changes required to implement the feature; has zero impact 
>on existing users; does not IMO decrease maintainability of the Heat 
>code base; and is entirely achievable before the Havana feature 
>freeze, which is only ~4 months from now.
>That said, I am not wedded to any of the particular details of this 
>proposal - though I do regard it as a real proposal, not just a straw 
>man. If anybody has suggestions for where I've got the requirements, 
>concepts or implementation ideas wrong then rip in. But I'd love to 
>hear either a discussion at the level of these concrete details or a 
>competing proposal at a similar level.
>For easier collation, please categorise your response as follows:
> (A) I'm appalled at the mere suggestion
> (B) This just prevents us solving the real problem (please specify)
> (C) Meh
> (D) This looks kind of interesting
>OpenStack-dev mailing list
>OpenStack-dev at lists.openstack.org

More information about the OpenStack-dev mailing list