[openstack-dev] [Heat] HOT Software configuration proposal
Keith Bray
keith.bray at RACKSPACE.COM
Mon Oct 28 23:14:49 UTC 2013
In-line comments.
On 10/28/13 5:43 PM, "Steve Baker" <sbaker at redhat.com> wrote:
>On 10/26/2013 05:25 AM, Clint Byrum wrote:
>> Excerpts from Angus Salkeld's message of 2013-10-24 18:48:16 -0700:
>>> On 24/10/13 11:54 +0200, Patrick Petit wrote:
>>>> Hi Clint,
>>>> Thank you! I have few replies/questions in-line.
>>>> Cheers,
>>>> Patrick
>>>> On 10/23/13 8:36 PM, Clint Byrum wrote:
>>>>> I think this fits into something that I want for optimizing
>>>>> os-collect-config as well (our in-instance Heat-aware agent). That is
>>>>> a way for us to wait for notification of changes to Metadata without
>>>>> polling.
>>>> Interesting... If I understand correctly that's kinda replacement of
>>>> cfn-hup... Do you have a blueprint pointer or something more
>>>> specific? While I see the benefits of it, in-instance notifications
>>>> is not really what we are looking for. We are looking for a
>>>> notification service that exposes an API whereby listeners can
>>>> register for Heat notifications. AWS Alarming / CloudFormation has
>>>> that. Why not Ceilometer / Heat? That would be extremely valuable for
>>>> those who build PaaS-like solutions above Heat. To say it bluntly,
>>>> I'd like to suggest we explore ways to integrate Heat with Marconi.
>>> Yeah, I am trying to do a PoC of this now. I'll let you know how
>>> it goes.
>>>
>>> I am trying to implement the following:
>>>
>>> heat_template_version: 2013-05-23
>>> parameters:
>>> key_name:
>>> type: String
>>> flavor:
>>> type: String
>>> default: m1.small
>>> image:
>>> type: String
>>> default: fedora-19-i386-heat-cfntools
>>> resources:
>>> config_server:
>>> type: OS::Marconi::QueueServer
>>> properties:
>>> image: {get_param: image}
>>> flavor: {get_param: flavor}
>>> key_name: {get_param: key_name}
>>>
>>> configA:
>>> type: OS::Heat::OrderedConfig
>>> properties:
>>> marconi_server: {get_attr: [config_server, url]}
>>> hosted_on: {get_resource: serv1}
>>> script: |
>>> #!/bin/bash
>>> logger "1. hello from marconi"
>>>
>>> configB:
>>> type: OS::Heat::OrderedConfig
>>> properties:
>>> marconi_server: {get_attr: [config_server, url]}
>>> hosted_on: {get_resource: serv1}
>>> depends_on: {get_resource: configA}
>>> script: |
>>> #!/bin/bash
>>> logger "2. hello from marconi"
>>>
>>> serv1:
>>> type: OS::Nova::Server
>>> properties:
>>> image: {get_param: image}
>>> flavor: {get_param: flavor}
>>> key_name: {get_param: key_name}
>>> user_data: |
>>> #!/bin/sh
>>> # poll <marconi url>/v1/queues/{hostname}/messages
>>> # apply config
>>> # post a response message with any outputs
>>> # delete request message
>>>
>> If I may diverge this a bit, I'd like to consider the impact of
>> hosted_on on reusability in templates. hosted_on feels like an
>> anti-pattern, and I've never seen anything quite like it. It feels wrong
>> for a well contained component to then reach out and push itself onto
>> something else which has no mention of it.
>>
>> I'll rewrite your template as I envision it working:
>>
>> resources:
>> config_server:
>> type: OS::Marconi::QueueServer
>> properties:
>> image: {get_param: image}
>> flavor: {get_param: flavor}
>> key_name: {get_param: key_name}
>>
>> configA:
>> type: OS::Heat::OrderedConfig
>> properties:
>> marconi_server: {get_attr: [config_server, url]}
>> script: |
>> #!/bin/bash
>> logger "1. hello from marconi"
>>
>> configB:
>> type: OS::Heat::OrderedConfig
>> properties:
>> marconi_server: {get_attr: [config_server, url]}
>> depends_on: {get_resource: configA}
>> script: |
>> #!/bin/bash
>> logger "2. hello from marconi"
>>
>> serv1:
>> type: OS::Nova::Server
>> properties:
>> image: {get_param: image}
>> flavor: {get_param: flavor}
>> key_name: {get_param: key_name}
>> components:
>> - configA
>> - configB
>> user_data: |
>> #!/bin/sh
>> # poll <marconi url>/v1/queues/{hostname}/messages
>> # apply config
>> # post a response message with any outputs
>> # delete request message
>>
>> This only becomes obvious why it is important when you want to do this:
>>
>> configC:
>> type: OS::Heat::OrderedConfig
>> properties:
>> script: |
>> #!/bin/bash
>> logger "?. I can race with A, no dependency needed"
>>
>> serv2:
>> type: OS::Nova::Server
>> properties:
>> ...
>> components:
>> - configA
>> - configC
>>
>> This is proper composition, where the caller defines the components, not
>> the callee. Now you can re-use configA with a different component in the
>> same template. As we get smarter we can have these configs separate from
>> the template and reusable across templates.
>>
>> Anyway, I'd like to see us stop talking about hosted_on, and if it has
>> been implemented, that it be deprecated and eventually removed, as it is
>> just plain confusing.
>>
>My components proposals had no hosted_on, but I've been thinking about
>the implications of implementing software configuration as resources,
>and one of the natural consequences might be that hosted_on is the best
>way of establishing the relationship with compute and its
>configurations. Let me elaborate.
>
>Lets say that Heat has resource types for software configuration, with
>the following behaviours:
>* like other resources, a config resource goes into CREATE IN_PROGRESS
>as soon as its dependencies are satisfied (these dependencies may be
>values signalled from other config resources)
>* a config resource goes to state CREATE COMPLETE when it receives a
>signal that configuration on the compute resource is complete (by some
>mechanism; wait condition, marconi message, whatevs)
>* the relationship between config resources and compute resources are
>achieved with existing intrinsic functions (get_resource, get_attr)
>
>This lifecycle behaviour means that a configuration resource can only
>run on a single compute resource, and that relationship needs to be
>established somehow. Config resources will have a quirk in that they
>need to provide 2 sources of configuration data at different times:
>1) cloud-init config-data (or other boot-only mechanism), which must be
>available when the compute resource goes into CREATE IN_PROGRESS
>2) the actual configuration data (oac metadata, puppet manifest, chef
>recipe) which the compute resource needs to be able to fetch and execute
>whenever it becomes available.
>
>The data in 1) implies that the compute needs to depend on the config,
>but then all concurrency is lost (this won't matter for a
>cloud-init-only config resource). Either way, the data for 1) will need
>to be available when the config resource is still in state INIT
>COMPLETE, which may impose limitations on how that is defined (ie
>get_resource, get_attr not allowed).
>
>So, 2 concrete examples for handling config/compute dependencies:
>
>hosted_on
>---------
>resources:
> configA
> type: Heat::ScriptConfig
> properties:
> hosted_on:
> get_resource: the_server
> script: |
> #!/bin/bash
> logger "1. hello config A"
> configB
> type: Heat::ScriptConfig
> properties:
> hosted_on:
> get_resource: the_server
> script: |
> #!/bin/bash
> logger "1. hello config B"
> the_server:
> type: OS::Nova::Server
>
>Here, configA and configB go into CREATE IN_PROGRESS as soon as
>the_server is CREATE COMPLETE. configA and configB go into CREATE
>COMPLETE when heat-engine receives a signal that they are complete. This
>signal may include values that other resources depend on to start their
>creation.
>
>OS::Nova::Server config_resources
>---------------------------------
>resources:
> configA
> type: Heat::ScriptConfig
> properties:
> script: |
> #!/bin/bash
> logger "1. hello config A"
> configB
> type: Heat::ScriptConfig
> properties:
> script: |
> #!/bin/bash
> logger "1. hello config B"
> the_server:
> type: OS::Nova::Server
> properties:
> config_resources:
> - {get_resource: configA}
> - {get_resource: configB}
>
>Here there would need to be some bypassing of dependency calculation to
>allow configA and configB to be created after the_server, maybe by:
>* special treatment of config_resources to prevent dependencies being
>created
>* a get_resource variant which doesn't create a hard dependency
>(get_resource_deferred?)
>
>Neither the hosted_on nor the config_resources behaviours are ideal, but
>I'm leaning towards hosted_on at the moment since it doesn't require any
>new soft-dependency mechanism.
For what it's worth, I prefer the config_resources method, because I want
to reuse configs across multiple servers. In the hosted_on
implementation, would there be a way to reuse configA on different servers
in the same stack? The logical organization of what software to apply to
a server just seems to make more sense to me when I look at the syntax for
config_resources. If I can specify multiple "hosted_on" servers for a
given config, then I could be ok with hosted_on, but still prefer
config_resources for the reason that it seems logical to define what
software you want installed on a server than to define what servers you
want to install a piece of software on. Nit picky on my part for sure, but
food for thought.
>
>As for composability, what *actually* needs to be composable is the
>contents of the script (manifest, recipe) property. Everything else in a
>config resource is just stack-specific wiring. There are a couple of
>ways this composability could be achieved:
>1) resource provider in the user environment which specifies the script
>property
>2) __include__ or some equivalent client-side inclusion mechanism
+1 to the __include__... This would be a useful feature to template
writers. What do you all think, should the include substitution logic live
in the python-heatclient so that Heat only ever receives the fully
composited template? (side note: I originally thought that stack based
resource providers worked as #includes... Turns out I was waaay wrong once
I understood them :-)
>
>With either of these options, intrinsic function calls need to be moved
>out of the script property and into a variables property. Any
>configuration management tool that supports variables passed as inputs
>can use them. If a given tool doesn't support variables then heat-engine
>could do the substitution when building the configuration data.
>
>Using resource providers has another interesting possibility. With a
>sufficiently advanced software-config base resource type, it should be
>possible to write a resource provider which adds support for a
>configuration management tool that heat otherwise knows nothing about.
A big thank you to all of you proposing ideas here and writing blueprints.
This is good stuff!
-Keith
More information about the OpenStack-dev
mailing list