Jump to: navigation, search

Difference between revisions of "Heat/Blueprints/hot-software-config-spec"

m (Implemenation considerations: - typo)
 
(34 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
= Background =
 
= Background =
This page presents a work-in-progress design for the HOT software configuration feature. It should be seen as an evolution a previous [[Heat/Blueprints/hot-software-config|hot-software-config]] proposal, but factoring in result of design discussion at the recent OpenStack summit in Hong Kong.
+
This page presents a work-in-progress design for the HOT software configuration feature. It should be seen as an evolution of a previous [[Heat/Blueprints/hot-software-config|hot-software-config]] proposal, but factoring in results of design discussions at the recent OpenStack summit in Hong Kong.
 
This refined proposal is captured as a new wiki page for readability reasons. Once the design is finalized, we will consolidate the various wiki pages into a single one.
 
This refined proposal is captured as a new wiki page for readability reasons. Once the design is finalized, we will consolidate the various wiki pages into a single one.
  
'''Discussions page:''' https://wiki.openstack.org/wiki/Talk:Heat/hot-software-config-WIP
+
'''Discussions page:''' https://wiki.openstack.org/wiki/Talk:Heat/hot-software-config-spec
 
 
  
 
= Requirements =
 
= Requirements =
Line 11: Line 10:
 
* '''Composability and re-use:''' It must be possible to define software components once and compose and re-use them in different contexts without duplicating definitions.
 
* '''Composability and re-use:''' It must be possible to define software components once and compose and re-use them in different contexts without duplicating definitions.
 
* '''Separation of component definitions and deployment:''' It must be possible to define multiple deployments of a software component, e.g. a software component defined once must be able to be deployed on different servers in a template.
 
* '''Separation of component definitions and deployment:''' It must be possible to define multiple deployments of a software component, e.g. a software component defined once must be able to be deployed on different servers in a template.
* '''Software components as stateful entities:''' It must be possible to track state of software components, i.e. whether a software deployment is in progress, has completed, or has failed. It must be possible to retrieve outputs (attributes) of software components.
+
* '''Software components as stateful entities:''' It must be possible to track state of software components, i.e. whether a software deployment is in progress, has completed, or has failed.  
 +
* '''Reference to software component outputs:''' It must be possible to retrieve outputs (attributes) of software components.
 
* '''Ability to express dependencies between software components:''' It must be possible to define dependencies between software component, e.g. that input for one component is obtained from output of another component.
 
* '''Ability to express dependencies between software components:''' It must be possible to define dependencies between software component, e.g. that input for one component is obtained from output of another component.
  
 +
= High level overview =
 +
Re-usable software components are modeled as <code>SoftwareConfig</code> resources. Those <code>SoftwareConfig</code> definitions point to the actual automation to later perform software configuration (e.g. Chef, Puppet, scripts, ...) and they provide the metadata that is necessary for a generic <code>SoftwareDeployment</code> resource to deploy a given software on a server. The <code>SoftwareDeployment</code> resource represents one incarnation, i.e. one concrete use, of a software component in a template. It provides specific input parameters for that deployment, it will provide outputs produced by that deployment, and most importantly it maps the deployment to a specific target server.
 +
 +
It is assumed that there will be different pluggable implementations for <code>SoftwareConfig</code> and <code>SoftwareDeployment</code> - one per backend configuration tool like Chef, Puppet, scripting etc. - since each configuration tool will have specific requirements on metadata and runtime implementation. Yet, it is assumed that a lot of common behavior can be covered by generic base classes for SoftwareConfig and SoftwareDeployment so only very thin plug-ins will be needed for the various CM tools (this is ongoing design work).
 +
 +
The following figure shows those concepts based on a Wordpress example. It is assumed that there are Chef cookbooks for configuring the Wordpress application and MySQL. Those are referenced by two <code>SoftwareConfig</code> resources, along with the respective metadata for each automation. The automation plus the corresponding <code>SoftwareConfig</code> definitions are the re-usable entities; they are not mapped to any concrete deployment target, and they do not define specific input values. There are two <code>SoftwareDeployment</code> resources, one for MySQL and one for Wordpress, each mapping the deployment to a separate server. A data dependency exists between the Wordpress deployment and the MySQL deployment (see also snippets later on this page) to get endpoint information about the MySQL database for configuring the Worpress application.
 +
 +
[[File:HOT-software-config-overview2.png|400px|none|center]]
 +
 +
For simple templates, it is possible to define all elements (SoftwareConfig, SoftwareDeployment and other base resources) in one template file. For more complex scenarios, and to increase composability, a subset of resources can be split into separate provider templates that can be bound via environments. This is explained in more detail and with example snippets in section [[Heat/Blueprints/hot-software-config-spec#Packaging_for_re-use_as_provider_templates|Packaging for re-use as provider templates]].
 +
 +
= Software Configs =
 +
<code>SoftwareConfig</code> resources contain definitions of metadata for automation like Chef cookbooks, scripts, etc. along with a reference to the actual automation. Once defined, they can be mapped to one or more deployment targets (servers) by means of <code>ServerDeployment</code> resources (see [[Heat/Blueprints/hot-software-config-spec#Software_Deployments|Software Deployments]]). SoftwareConfig definitions are specific to the used software configuration tool, since they provide tool specific metadata. The following example shows a snippet for a Chef Software Config resource (the complete example is given in section [[Heat/Blueprints/hot-software-config-spec#Wordpress_all-in-one_Example|Wordpress all-in-one Example]]):
  
= High level overview =
+
resources:
The following figure shows a high level overview of the design idea. Software components are defined in a separate file that can be referenced from templates that want to make use of the respective software component definition. The component definition defines inputs (configurable parameters) and outputs of the software component, it points to the automation like Chef, Puppet or scripts for doing the actual software configuration, and it includes specifics for the respective automation being used (e.g. chef specific parameters).
+
  wordpress_sw_config:
 +
    type: OS::Heat::SoftwareConfig::Chef
 +
    properties:
 +
      cookbook: http://www.example.com/hot/chef/wordpress.zip
 +
      role: wordpress
 +
      # input parameters that the chef role(s) need
 +
      inputs:
 +
        wp_admin_user:
 +
          type: string
 +
          mapping: wordpress/admin_user
 +
        wp_admin_pw:
 +
          type: string
 +
          mapping: wordpress/admin_password
 +
        db_endpoint_url:
 +
          type: string
 +
          mapping: wordpress/db_url
 +
        # more input parameters ...
 +
      # output data that the chef automation produces
 +
      outputs:
 +
        wp_url:
 +
          type: string
 +
          mapping: wordpress/url
  
A "Software Deployment" resource in a HOT template represents one specific use of the software component, i.e. a concrete deployment on a server. There can be multiple deployments of the same software component, e.g. on two servers, which would be modeled as two separate software deployment resources.
+
The resource type <code>OS::Heat::SoftwareConfig::Chef</code> indicates that this is a Chef-specific Software Config definition. The <code>cookbook</code> property points to the used Chef cookbook, and the <code>role</code> property points to the role to be set up via this Software Config. The <code>inputs</code> section contains the definition of input parameters that have to be passed to Chef for configuring the role. Input parameters are defined in terms of name and type. In addition, a <code>mapping</code> specifies to which role attribute the respective input parameters needs to be assigned (i.e. Chef-specific metadata).
  
[[File:HOT-software-config-overview.png|400px|none|center]]
+
The <code>outputs</code> section defines attributes that can be retrieved once the software deployment has completed at runtime. Those values will be available as attributes of the corresponding <code>SoftwareDeployment</code> resource at runtime (see also [[Heat/Blueprints/hot-software-config-spec#Software_Deployments|Software Deployments]]).
  
 +
= Software Deployments =
 +
A <code>SoftwareDeployment</code> resource represents one concrete use of a piece of software (defined via a <code>SoftwareConfig</code> resource) in a template. It points to the SoftwareConfig that shall be applied to a deployment target, and it points to the actual deployment target (server). As with SoftwareConfig, it is assumed that SoftwareDeployment implementations will be specific to the used software configuration tools, since tool specific steps will have to be performed at runtime.
  
= Software Deployment modeling in a HOT template =
+
The following example shows a SoftwareDeployment definition for the Wordpress component defined earlier using Chef. For brevity, definitions of overall template parameters, outputs or other resources have been left out - please refer to section [[Heat/Blueprints/hot-software-config-spec#Wordpress_all-in-one_Example|Wordpress all-in-one Example]] for the complete example:
One concrete deployment of a software component (i.e. one instance of the software installed at runtime) is modeled in a HOT template as one resource which points to the software component definition and defines the data flow (inputs as properties, outputs as attributes references from other parts of the template) in the context of the template. The resource fuirther has a reference to the server on which the software gets installed.
 
  
  heat_template_version: 2013-05-23
+
  resources:
 +
  wordpress_sw_config:
 +
    type: OS::Heat::SoftwareConfig::Chef
 +
    properties:
 +
      # ...
 
   
 
   
resources:
+
   wordpress_deployment:
   mysql:
+
     type: OS::Heat::SoftwareDeployment::Chef
     type: My::Software::MySQL
 
 
     properties:
 
     properties:
       server: { get_resource: db_server }
+
      apply_config: { get_resource: wordpress_sw_config }
       params:
+
       server: { get_resource: wp_server }
         db_name: { get_param: db_name }
+
       input_values:
         db_user: { get_param: db_user }
+
         wp_admin_user: { get_param: wp_admin_user }
         db_pw: { get_param: db_pw }
+
         wp_admin_pw: { get_param: wp_admin_pw }
 +
         # more input parameters ...
 
   
 
   
   db_server:
+
   wp_server:
 
     type: OS::Nova::Server
 
     type: OS::Nova::Server
 
     properties:
 
     properties:
       image: F19-x86_64-cfntools
+
       # ...
      flavor: m1.small
+
 
 +
The <code>wordpress_deployment</code> resource points to the <code>wordpress_sw_config</code> SoftwareConfig resource and specifies that one incarnation of it shall be deployed on (applied to) server <code>wp_server</code>. In the <code>input_values</code> section of the SoftwareDeployment properties, input for the configurable parameters of the Wordpress deployment is provided, for example, by getting global template parameters specified by the user at deployment time. Those parameters map to those defined in the <code>wordpress_sw_config</code> resource shown earlier.
 +
 
 +
The output parameters defined under <code>outputs</code> in the <code>wordpress_sw_config</code> resource can be observed as attributes of the <code>wordpress_deployment</code> resource via the <code>get_attr</code> instrinsic function. For example, the following snippet in a HOT template would pass the URL of the deployed Wordpress application to the user as an output value:
 +
 
 +
outputs:
 +
  wordpress_url:
 +
    description: URL to access deployed Wordpress application
 +
    value: { get_attr: [ wordpress_deployment, wp_url ]}
  
The <code>mysql</code> resource in the snippet above is of type <code>My::Software::MySQL</code> (which is an arbitrary resource type) and represents a deployment of MySQL on a server. By means of an environment resource mapping, that type name gets bound to a concrete software component definition (see below). The <code>server</code> property is a reference to the server on which the software will be installed. The server itself is modeled as the <code>db_server</code> resource in the template.
 
  
The advantage of using an environment mapping of the resource type name of the <code>mysql</code> resource is that the template itself does not point to one concrete software component definition in a hardcoded fashion, but that alternative definitions can be used thru the respective environment mapping as long as they have the same signature (inputs and outputs). For example, this would allow for having one component definition that will work on F19 images and another one that will work on Ubuntu images.
+
== Responsibilities of the Software Deployment Resource ==
Another example is that the current provider template resource implementation can be used (probably without any changes).
+
There are several aspects to be covered by implementations of Software Deployment resources. First of all, the resource code is responsible for injecting metadata into the referenced deployed target (server) for doing bootstrapping of the respective software config tool (Chef etc.). Furthermore, the resource is responsible for triggering deployment of the respective software (by invoking the underlying software config tool) when all dependencies are met. Upon completion of software deployment, the resource has to update its state to CREATE_COMPLETE so overall orchestration through Heat can progress (or failures have to be indicated via the appropriate failure state). Finally, attributes specified in the associated SoftwareConfig resource have to be obtained from the underlying software config tool so that uses of the <code>get_attr</code> can be resolved.
  
== Design alternative ==
+
= Dependencies between Software Deployments =
As an alternative, we could implement  generic SoftwareDeployment resource type (<code>OS::Heat::SoftwareDeployment</code>) and let it point to the software component definition via a property, e.g. a <code>component</code> property:
+
Software Deployments in many cases depend on other Software Deployments. For example, the Wordpress application requires a MySQL database to be set up for storing content. There are two ways for declaring dependencies between Software Deployments: ''data flow based'' and ''explicit definition''.
 +
 
 +
== Data flow based ==
 +
A data flow based dependency between two Software Deployments exists, when a property (input) of one Software Deployment is obtained from an attribute (output) of another Software Deployment. A dependency between the two SoftwareDeployment resources is enforced by the Heat engine implicitly. For example
  
 
  resources:
 
  resources:
   mysql:
+
   wordpress_deployment:
     type: OS::Heat::SoftwareDeployment
+
     type: OS::Heat::SoftwareDeployment::Chef
 +
    properties:
 +
      apply_config: { get_resource: wordpress_sw_config }
 +
      server: { get_resource: wp_server }
 +
      input_values:
 +
        wp_admin_user: { get_param: wp_admin_user }
 +
        wp_admin_pw: { get_param: wp_admin_pw }
 +
        db_endpoint_url: { get_attr: [ mysql_deployment, db_url ] }
 +
        # more input parameters ...
 +
 +
  mysql_deployment:
 +
    type: OS::Heat::SoftwareDeployment::Chef
 
     properties:
 
     properties:
       component: http://www.example.com/hot/components/MySQL.yaml
+
       apply_config: { get_resource: mysql_sw_config }
 
       server: { get_resource: db_server }
 
       server: { get_resource: db_server }
       params:
+
       input_values:
         # ...
+
         # input parameters for MySQL deployment ...
 +
 
 +
would introduce a dependency from <code>wordpress_deployment</code> to <code>mysql_deployment</code> since one of the properties of <code>wordpress_deployment</code> is set using the <code>get_attr</code> function refering to an attribute of the <code>mysql_deployment</code> resource. As a result, resource <code>mysql_deployment</code> must be in state CREATE_COMPLETE before processing of resource <code>wordpress_deployment</code> starts. The complete example is shown in section [[Heat/Blueprints/hot-software-config-spec#Wordpress_all-in-one_Example|Wordpress all-in-one Example]].
 +
 
 +
== Explicit dependency ==
 +
If no data dependency exists, but there is still a timing dependency (e.g. a process must be up before a client can connect to it), a mechanism for declaring an explicit dependency is required. This can be solved by explicitly defining dependencies of a software deployment in a <code>depends_on</code> clause which is a list of resource IDs of other resources that a Software Deployment depends on, for example:
  
The referenced component definition (MySQL.yaml in the example above) is like a nested template, but the SoftwareDeployment resource could implement specific code (to be defined) that is not necessary in the generic provide template resource.
+
resources:
 +
  client:
 +
    type: OS::Heat::SoftwareDeployment::Chef
 +
    properties:
 +
      apply_config: { get_resource: client_sw_config }
 +
      server: { get_resource: my_server }
 +
      input_values:
 +
        # params ...
 +
    depends_on:
 +
      - get_resource: server_process1
 +
      - get_resource: server_process2
 +
 +
  server_process1:
 +
    type: OS::Heat::SoftwareDeployment::Chef
 +
    properties:
 +
      apply_config: { get_resource: server_process1_sw_config }
 +
      server: { get_resource: my_server }
 +
      input_values:
 +
        # params ...
 +
 +
  server_process2:
 +
    type: OS::Heat::SoftwareDeployment::Chef
 +
    properties:
 +
      apply_config: { get_resource: server_process2_sw_config }
 +
      server: { get_resource: my_server }
 +
      input_values:
 +
        # params ...
 +
 +
  my_server:
 +
    type: OS::Nova::Server
 +
    properties:
 +
      # ...
  
Pros: more obvious modeling of a "software deployment"; ability to have special code in the SoftwareDeployment resource
+
In the example above, <code>client</code> would depend on both <code>server_process1</code> and <code>server_process2</code> to be completed.
  
Cons: pretty close to provide template concept, but not really the same (which could be confusing); hardcoded pointer to one specific software component definition, which requires change to the template for pointing to an alternative definition.
 
  
 +
= Packaging for re-use as provider templates =
 +
In descriptions given so far it was outlined how <code>SoftwareConfig</code> and <code>SoftwareDeployment</code> can be used in a HOT template to address software orchestration in Heat. For simple examples or for getting started, it is possible to put all definitions into a single template file. However, to make definitions more re-usable or when it comes to bigger, more complex scenarios, it makes sense to split definitions of software components into separate files. For example, instead of having the Software Config definition of the Wordpress application (<code>wordpress_sw_config</code> in examples above) with all details (pointer to Chef cookbook, definition of inputs and outputs etc.) duplicated in each template that uses Wordpress, it is better to put those definitions into one file that can be leveraged by other templates as a ''provider template''.
  
= Software component definition =
+
One possible option is to define both the <code>SoftwareConfig</code> resource and the <code>SoftwareDeployment</code> resource for the Wordpress application in a separate template file and provide all input parameters as well as the pointer to the target server as input when using the provider template. The corresponding provider template would look like the following snippet (complete example given in section [[Heat/Blueprints/hot-software-config-spec#Wordpress_example_with_re-usable_provider_templates|Wordpress example with re-usable provider templates]]):
The definition of a software component, i.e. its inputs, outputs, pointer to the actual automation for deploying the software etc. is provided as a separate template file that uses the exact same syntax as any other HOT template file. For example, the template below would contain the definition of the MySQL component used in the snippets shown earlier.
 
  
 
  heat_template_version: 2013-05-23
 
  heat_template_version: 2013-05-23
 
description: >
 
  This template contains the definition of the MySQL software component.
 
  It defines configuration parameters (inputs), outputs, and links to the actual automation.
 
 
   
 
   
 
  parameters:
 
  parameters:
   server:
+
   wp_admin_user:
     description: The server onto which to deploy the MySQL software component.
+
     description: Username of the Wordpress admin user.
 
     type: string
 
     type: string
   db_name:
+
   wp_admin_pw:
     description: The name of the database to be created.
+
     description: Password of the Wordpress admin user.
 
     type: string
 
     type: string
    constraints:
+
   db_endpoint_url:
      - length: { min: 6, max: 10 }
+
     description: Endpoint URL of the database to be used.
        description: DB name must be between 6 and 10 characters.
 
   db_user:
 
     description: The username for the DB admin user.
 
 
     type: string
 
     type: string
   db_pw:
+
   # more software related parameters ...
     description: The password for the DB admin user.
+
 +
  server:
 +
     description: Reference to server onto which to install Wordpress.
 
     type: string
 
     type: string
    hidden: true
 
 
   
 
   
 
  resources:
 
  resources:
   mysql:
+
   wordpress_sw_config:
     type: OS::Heat::ChefSoftwareComponent
+
     type: OS::Heat::SoftwareConfig::Chef
 +
    properties:
 +
      cookbook: http://www.example.com/hot/chef/wordpress.zip
 +
      role: wordpress
 +
      # input parameters that the chef role(s) need
 +
      inputs:
 +
        # ...
 +
      # output data that the chef automation produces
 +
      outputs:
 +
        # ...
 +
 +
  wordpress_deployment:
 +
    type: OS::Heat::SoftwareDeployment::Chef
 
     properties:
 
     properties:
 +
      apply_config: { get_resource: wordpress_sw_config }
 
       server: { get_param: server }
 
       server: { get_param: server }
       cookbook: http://www.example.com/hot/chef/mysql.zip
+
       input_values:
      params:
+
         wp_admin_user: { get_param: wp_admin_user }
         db_name: { get_param: db_name }
+
         wp_admin_pw: { get_param: wp_admin_pw }
         db_user: { get_param: db_user }
+
         db_endpoint_url: { get_param: db_endpoint_url }
         db_pw: { get_param: db_pw }
+
        # ...
 
   
 
   
 
  outputs:
 
  outputs:
   mysql_port:
+
   wordpress_url:
     description: The port assigned to the MySQL database.
+
     description: URL to access deployed Wordpress application
     value: { get_attr: [ mysql, port ] }
+
     value: { get_attr: [ wordpress_deployment, wp_url ]}
  
The <code>parameters</code> sections define any input parameters that should be configurable by the user of this component definition such as the database name in the example above. By convention, software component definitions will always define a <code>server</code> property to allow the server on which to install the software be specified by the user.
+
Note that even though the <code>SoftwareDeployment</code> resource is contained within the provider template, the definition is still re-usable since no mapping to any server is defined. A reference to the server on which the Software Deployment shall be run is provided as input parameter in the place where the provider template is used. This is achieved by having the <code>server</code> parameter defined in the <code>parameters</code> section of the template, and by having the <code>server</code> property of the <code>wordpress_deployment</code> resource be initialized with the user-provided parameter.
  
The <code>mysql</code> resource contains the definition of who MySQL gets installed. The type <code>OS::Heat:ChefSoftwareComponent</code> indicates that installation will be done using chef. The assumption is that we will have a set of "adapters" for commonly used software configuration tools as resource plugins to Heat, for example for Chef, Puppet, scripts etc. We can probably have a base class that implements generic behavior such as interpretation of the <code>server</code> property to do bootstrapping actions. Specific adapter resources can then inherit common behavior and we have some extension point for adding custom adapter resources.
+
Note that in addition to having better re-usability of Software Config definitions in contrast to having them included in the actual template file, the approach of defining them in provider templates also offers the possibility to do richer input parameter validation, since the <code>parameters</code> section of a HOT template features more schema-like expressiveness through <code>constraints</code> that can be expressed for each input parameter.
  
== Software component inputs ==
+
With a re-usable definition for MySQL in a similar file, a HOT template for an actual deployment can then be composed as outlined in the following snippet:
By means of the <code>parameters</code> section, the component author can clearly define, what input the software component requires or allows, also leveraging constraints for inputs. It defines the properties schema of the "software deployment" resource in the actual template (see earlier). Thus it is possible to make sure the input actually maps the actually used implementation (e.g. the used chef cookbook). All the code for supporting this already exists (provide template resource etc.), the syntax is described for HOT, so we do not have to do anything for leveraging this feature.
 
  
== Software component outputs ==
+
heat_template_version: 2013-05-23
The <code>outputs</code> section declares what data the software deployment produces that can be used in other parts of the template, e.g. as input for other software components. For example, the port assigned to the MySQL database by the underlying Chef automation can be returned so that an application can bind to it. The code for mapping outputs as attributes of a provider resource again already exists in the provider template resource, and the syntax is document thru the HOT specification.
+
 +
parameters:
 +
  # parameter definitions omitted for brevity
 +
 +
resources:
 +
  wordpress:
 +
    type: Software::Wordpress
 +
    properties:
 +
      server: { get_resource: wp_server }
 +
      wp_admin_user: { get_param: wp_admin_user }
 +
      wp_admin_pw: { get_param: wp_admin_pw }
 +
      db_endpoint_url: { get_attr: [ mysql, db_endpoint_url ] }
 +
      db_user: { get_param: db_user }
 +
      db_pw: { get_param: db_pw }
 +
 +
  wp_server:
 +
    type: OS::Nova::Server
 +
    properties:
 +
      image: { get_param: image }
 +
      flavor: { get_param: flavor }
 +
 +
  mysql:
 +
    type: Software::MySQL
 +
    properties:
 +
      server: { get_resource: db_server }
 +
      db_user: { get_param: db_user }
 +
      db_pw: { get_param: db_pw }
 +
      db_name: { get_param: db_name }
 +
 +
  db_server:
 +
    type: OS::Nova::Server
 +
    properties:
 +
      image: { get_param: image }
 +
      flavor: { get_param: flavor }
 +
 +
outputs:
 +
  wordpress_url:
 +
    description: URL to access deployed Wordpress application
 +
    value: { get_attr: [ wordpress_deployment, wp_url ]}
  
== Software config resource ==
+
The template above does not contain the detailed definitions of the Wordpress and MySQL Software Configs any more, but just defines two concrete uses of those software components - the <code>wordpress</code> resource and the <code>mysql</code> resource. The target server for each use, as well as specific input parameters are provided as properties to those resources.
The actual software config resource (<code>mysql</code> resource in the example above) makes use of generic implementations to adapt to a given software config tool (e.g. Chef). The responsibility of such resource implementations is to:
 
* perform bootstrapping of the respective software config tool on the server provided thru the <code>server</code> property
 
* invoke the respective software config tool, passing to it all the additional parameters in the <code>params</code> sub-section of the <code>properties</code> section (data type of the <code>params</code> section in the properties schema would be a map.
 
* wait for completion of the invoked automation
 
* collect return values and provide them as attributes of the software deployment resource
 
* signal completion of the software configuration task so that dependent deployment steps can be started
 
  
 +
The resource type names used for both resources, <code>Software::Wordpress</code> or <code>Software::MySQL</code>, are bound to the respective provider templates by means of environment definitions. This also provides for more flexibility, since different provider templates may be used in different environments without having to change the template. For example, there may be provider templates for software that work well on Fedora but others that work on Ubuntu.
  
Note that since the software config resource (<code>mysql</code> resource in example above) is just like any other resource, it could also be directly used in a HOT template without having to define a software component definition in a separate template file. You would lose aspects like re-use of component definition, lose coupling to a concrete implementation etc. in this case, though.
+
Assuming that the definition of the Wordpress component is contained in a provider templates with name <code>wordpress_component.yaml</code> and the definition for MySQL is contained in a file <code>mysql_component.yaml</code> - both available on a server - a corresponding environment definition would look like the following:
  
 +
resource_registry:
 +
  "Software::Wordpress": http://www.example.com/hot/software/wordpress_component.yaml
 +
  "Software::MySQL": http://www.example.com/hot/software/mysql_component.yaml
  
= Composite software components =
+
= Implementation considerations =
Since a software component definition as described in the previous section is just a regular HOT template, it is easy to also define composite software components that include multiple, potentially dependent modules that look from the outside like a single software components. Inputs to the composite software component (via the <code>parameters</code> section of the software component template file) can be distributed to properties of internal components.
+
This section is still very much in progress, but more or less a collection of some thoughts for now.
  
 +
Bootstrapping of software configuration tools could be done using cloud-init. The software configuration resource implementation will have to inject the respective metadata into the server resource definition on which it is hosted.
  
= Data flow between software deployments =
+
Implementations like <code>os-collect-config</code> etc. could be used for collecting software config metadata etc.
Since software deployments (uses of software components in a concrete template) are modeled as normal Heat resources, any mechanism for passing data between resources that works for Heat resources today will work for passing data between software components should just work.
 
  
Inputs to software deployments can be provided by setting properties of the "software deployment" resources in a template.
+
For synchronization purposes (e.g. in case of an explicit dependency), existing mechanisms (e.g. WaitCondition signaling) could be used under the covers, however, without surfacing them in templates.
  
Outputs from software deployments can be read by means of the <code>get_attr</code> intrinsic function.
+
= Wordpress all-in-one Example =
 
+
The following listing shows the Wordpress example referenced earlier as a complete HOT template. The template includes all definitions of Software Configs, Software Deployments, as well as server resources (thus ''all-in-one'' example). '''Note''' that the example is not meant to be 100% correct so it could be used in Heat, but it is meant to give a complete end-to-end draft of the concepts described on this wiki page.
= Dependencies between software deployments =
 
There are two ways for declaring dependencies between software deployments: ''data flow based'' and ''explicit definition''.
 
 
 
== Data flow based ==
 
A data flow based dependency between two software deployments exists, when a property (input) of one software deployment is obtained from an attribute (output) of another software deployment. A dependency between the two "software deployment" resources is enforced by the Heat engine implicitly. For example
 
  
 +
heat_template_version: 2013-05-23
 +
 +
description: >
 +
  This is an all-in-one template for deployment of Wordpress and MySQL on two servers.
 +
  The definition of software configs for Wordpress and MySQL as well as definition for
 +
  deployment onto servers is contained in this single template file.
 +
 +
parameters:
 +
  wp_admin_user:
 +
    description: Username of the Wordpress admin user.
 +
    type: string
 +
  wp_admin_pw:
 +
    description: Password of the Wordpress admin user.
 +
    type: string
 +
  db_user:
 +
    description: Username of the database admin user.
 +
    type: string
 +
  db_pw:
 +
    description: Password of the database admin user.
 +
    type: string
 +
  db_name:
 +
    description: Database name for the Wordpress database.
 +
    type: string
 +
  image:
 +
    description: Image to be used for servers.
 +
    type: string
 +
  flavor:
 +
    description: Flavor to be used for servers.
 +
    type: string
 +
 
  resources:
 
  resources:
   wordpress:
+
   wordpress_sw_config:
     type: My::Software::Wordpress
+
    type: OS::Heat::SoftwareConfig::Chef
 +
    properties:
 +
      cookbook: http://www.example.com/hot/chef/wordpress.zip
 +
      role: wordpress
 +
      # input parameters that the chef role(s) need
 +
      inputs:
 +
        wp_admin_user:
 +
          type: string
 +
          mapping: wordpress/admin_user
 +
        wp_admin_pw:
 +
          type: string
 +
          mapping: wordpress/admin_password
 +
        db_endpoint_url:
 +
          type: string
 +
          mapping: wordpress/db_url
 +
        db_user:
 +
          type: string
 +
          mapping: wordpress/db_user
 +
        db_pw:
 +
          type: string
 +
          mapping: wordpress/db_password
 +
      # output data that the chef automation produces
 +
      outputs:
 +
        wp_url:
 +
          type: string
 +
          mapping: wordpress/url
 +
 +
  wordpress_deployment:
 +
     type: OS::Heat::SoftwareDeployment::Chef
 
     properties:
 
     properties:
       server: { get_resource: web_server }
+
      apply_config: { get_resource: wordpress_sw_config }
       params:
+
       server: { get_resource: wp_server }
 +
       input_values:
 
         wp_admin_user: { get_param: wp_admin_user }
 
         wp_admin_user: { get_param: wp_admin_user }
 
         wp_admin_pw: { get_param: wp_admin_pw }
 
         wp_admin_pw: { get_param: wp_admin_pw }
         mysql_host: { get_attr: [ db_server, first_address ] }
+
         db_endpoint_url: { get_attr: [ mysql_deployment, db_url ] }
         mysql_port: { get_attr: [ msql, port ] }
+
         db_user: { get_param: db_user }
 +
        db_pw: { get_param: db_pw }
 
   
 
   
   mysql:
+
   wp_server:
     type: My::Software::MySQL
+
    type: OS::Nova::Server
 +
    properties:
 +
      image: { get_param: image }
 +
      flavor: { get_param: flavor }
 +
 +
  mysql_sw_config:
 +
    type: OS::Heat::SoftwareConfig::Chef
 +
    properties:
 +
      cookbook: http://www.example.com/hot/chef/mysql.zip
 +
      role: mysql-server
 +
      # input parameters that the chef role(s) need
 +
      inputs:
 +
        db_name:
 +
          type: string
 +
          mapping: mysql-server/db_name
 +
        db_user:
 +
          type: string
 +
          mapping: mysql-server/db_user
 +
        db_pw:
 +
          type: string
 +
          mapping: mysql-server/db_password
 +
      # output data that the chef automation produces
 +
      outputs:
 +
        db_endpoint_url:
 +
          type: string
 +
          mapping: mysql-server/db_url
 +
 +
  mysql_deployment:
 +
     type: OS::Heat::SoftwareDeployment::Chef
 
     properties:
 
     properties:
 +
      apply_config: { get_resource: mysql_sw_config }
 
       server: { get_resource: db_server }
 
       server: { get_resource: db_server }
       params:
+
       input_values:
 
         db_name: { get_param: db_name }
 
         db_name: { get_param: db_name }
 
         db_user: { get_param: db_user }
 
         db_user: { get_param: db_user }
 
         db_pw: { get_param: db_pw }
 
         db_pw: { get_param: db_pw }
 +
 +
  db_server:
 +
    type: OS::Nova::Server
 +
    properties:
 +
      image: { get_param: image }
 +
      flavor: { get_param: flavor }
 +
 +
outputs:
 +
  wordpress_url:
 +
    description: URL to access deployed Wordpress application
 +
    value: { get_attr: [ wordpress_deployment, wp_url ]}
  
would introduce a dependency from <code>wordpress</code> to <code>mysql</code> since two of the properties of <code>wordpress</code> are set using the <code>get_attr</code> function refering to attributes of the <code>mysql</code> resource. As a result, resource <code>mysql</code> must be in state CREATE_COMPLETE before processing of resource <code>wordpress</code> starts.
+
= Wordpress example with re-usable provider templates =
 +
In section [[Heat/Blueprints/hot-software-config-spec#Wordpress_all-in-one_Example|Wordpress all-in-one Example]] a HOT template was shown that included all definitions in a single file. This section lists the complete definitions of the same example, but with parts split into separate HOT templates that can be used as provider templates for better re-use.
  
== Explicit dependency ==
+
== Provider template for Wordpress ==
If no data dependency exists, but there is still a timing dependency (e.g. a process must be up before a client can connect to it), a mechanism for declaring an explicit dependency is required. This can be solved by giving each software deployment a <code>depends_on</code> property which is a list of resource IDs of other resources that a software deployment depends on, for example:
+
wordpress_component.yaml:
  
 +
heat_template_version: 2013-05-23
 +
 +
description: >
 +
  This template contains the definition of a Wordpress SoftwareConfig and
 +
  corresponding SoftwareDeployment for re-use in other templates as a HOT
 +
  provider template.
 +
 +
parameters:
 +
  wp_admin_user:
 +
    description: Username of the Wordpress admin user.
 +
    type: string
 +
  wp_admin_pw:
 +
    description: Password of the Wordpress admin user.
 +
    type: string
 +
  db_endpoint_url:
 +
    description: Endpoint URL of the database to be used.
 +
    type: string
 +
  db_user:
 +
    description: Username to connect to the database.
 +
    type: string
 +
  db_pw:
 +
    description: Password to connect to the database.
 +
    type: string
 +
  server:
 +
    description: Reference to server onto which to install Wordpress.
 +
    type: string
 +
 
  resources:
 
  resources:
   client:
+
   wordpress_sw_config:
     type: My::Software::SomeClient
+
     type: OS::Heat::SoftwareConfig::Chef
 +
    properties:
 +
      cookbook: http://www.example.com/hot/chef/wordpress.zip
 +
      role: wordpress
 +
      # input parameters that the chef role(s) need
 +
      inputs:
 +
        wp_admin_user:
 +
          type: string
 +
          mapping: wordpress/admin_user
 +
        wp_admin_pw:
 +
          type: string
 +
          mapping: wordpress/admin_password
 +
        db_endpoint_url:
 +
          type: string
 +
          mapping: wordpress/db_url
 +
        db_user:
 +
          type: string
 +
          mapping: wordpress/db_user
 +
        db_pw:
 +
          type: string
 +
          mapping: wordpress/db_password
 +
      # output data that the chef automation produces
 +
      outputs:
 +
        wp_url:
 +
          type: string
 +
          mapping: wordpress/url
 +
 +
  wordpress_deployment:
 +
    type: OS::Heat::SoftwareDeployment::Chef
 
     properties:
 
     properties:
       server: { get_resource: my_server }
+
      apply_config: { get_resource: wordpress_sw_config }
       depends_on:
+
       server: { get_param: server }
         - get_resource: server_process1
+
       input_values:
        - get_resource: server_process2
+
        wp_admin_user: { get_param: wp_admin_user }
      params:
+
        wp_admin_pw: { get_param: wp_admin_pw }
        # params ...
+
         db_endpoint_url: { get_param: db_endpoint_url }
 +
        db_user: { get_param: db_user }
 +
        db_pw: { get_param: db_pw }
 +
 +
outputs:
 +
  wordpress_url:
 +
    description: URL to access deployed Wordpress application
 +
    value: { get_attr: [ wordpress_deployment, wp_url ]}
 +
 
 +
== Provider template for MySQL ==
 +
mysql_component.yaml
 +
 
 +
heat_template_version: 2013-05-23
 +
 +
description: >
 +
  This template contains the definition of a MySQL SoftwareConfig and
 +
  corresponding SoftwareDeployment for re-use in other templates as a HOT
 +
  provider template.
 +
 +
parameters:
 +
  db_user:
 +
    description: Username of the database admin user.
 +
    type: string
 +
  db_pw:
 +
    description: Password of the database admin user.
 +
    type: string
 +
  db_name:
 +
    description: Database name for the Wordpress database.
 +
    type: string
 +
  server:
 +
    description: Reference to server onto which to install MySQL.
 +
    type: string
 
   
 
   
   server_process1:
+
resources:
     type: My::Software::SomeServer
+
   mysql_sw_config:
 +
     type: OS::Heat::SoftwareConfig::Chef
 
     properties:
 
     properties:
       server: { get_resource: my_server }
+
       cookbook: http://www.example.com/hot/chef/mysql.zip
       params:
+
      role: mysql-server
         # params ...
+
      # input parameters that the chef role(s) need
 +
      inputs:
 +
        db_name:
 +
          type: string
 +
          mapping: mysql-server/db_name
 +
        db_user:
 +
          type: string
 +
          mapping: mysql-server/db_user
 +
        db_pw:
 +
          type: string
 +
          mapping: mysql-server/db_password
 +
      # output data that the chef automation produces
 +
       outputs:
 +
         db_endpoint_url:
 +
          type: string
 +
          mapping: mysql-server/db_url
 
   
 
   
   server_process2:
+
   mysql_deployment:
     type: My::Software::SomeOtherServer
+
     type: OS::Heat::SoftwareDeployment::Chef
 
     properties:
 
     properties:
       server: { get_resource: my_server }
+
      apply_config: { get_resource: mysql_sw_config }
       params:
+
       server: { get_param: server }
         # params ...
+
       input_values:
 +
        db_name: { get_param: db_name }
 +
         db_user: { get_param: db_user }
 +
        db_pw: { get_param: db_pw }
 +
 +
outputs:
 +
  db_endpoint_url:
 +
    description: Endpoint URL of the MySQL database.
 +
    value: { get_attr: [ mysql_deployment, db_endpoint_url ]}
  
In the example above, <code>client</code> would depend on both <code>server_process1</code> and <code>server_process2</code> to be completed.
+
== HOT template to deploy Wordpress and MySQL on two servers ==
 +
wp-with-provider-templates.yaml:
  
 +
heat_template_version: 2013-05-23
 +
 +
description: >
 +
  This is a template for deployment of Wordpress and MySQL on two servers. The
 +
  definition of the software configs for Wordpress and MySQL are contained in
 +
  separate files that are bound as provider templates via the environment.
 +
 +
parameters:
 +
  wp_admin_user:
 +
    description: Username of the Wordpress admin user.
 +
    type: string
 +
  wp_admin_pw:
 +
    description: Password of the Wordpress admin user.
 +
    type: string
 +
  db_user:
 +
    description: Username of the database admin user.
 +
    type: string
 +
  db_pw:
 +
    description: Password of the database admin user.
 +
    type: string
 +
  db_name:
 +
    description: Database name for the Wordpress database.
 +
    type: string
 +
  image:
 +
    description: Image to be used for servers.
 +
    type: string
 +
  flavor:
 +
    description: Flavor to be used for servers.
 +
    type: string
 +
 +
resources:
 +
  wordpress:
 +
    type: Software::Wordpress
 +
    properties:
 +
      server: { get_resource: wp_server }
 +
      wp_admin_user: { get_param: wp_admin_user }
 +
      wp_admin_pw: { get_param: wp_admin_pw }
 +
      db_endpoint_url: { get_attr: [ mysql, db_endpoint_url ] }
 +
      db_user: { get_param: db_user }
 +
      db_pw: { get_param: db_pw }
 +
 +
  wp_server:
 +
    type: OS::Nova::Server
 +
    properties:
 +
      image: { get_param: image }
 +
      flavor: { get_param: flavor }
 +
 +
  mysql:
 +
    type: Software::MySQL
 +
    properties:
 +
      server: { get_resource: db_server }
 +
      db_user: { get_param: db_user }
 +
      db_pw: { get_param: db_pw }
 +
      db_name: { get_param: db_name }
 +
 +
  db_server:
 +
    type: OS::Nova::Server
 +
    properties:
 +
      image: { get_param: image }
 +
      flavor: { get_param: flavor }
 +
 +
outputs:
 +
  wordpress_url:
 +
    description: URL to access deployed Wordpress application
 +
    value: { get_attr: [ wordpress_deployment, wp_url ]}
  
= Implemenation considerations =
 
This section is still very much in progress, but more or less a collection of some thoughts for now.
 
 
Bootstrapping of software configuration tools could be done using cloud-init. The software configuration resource implementation will have to inject the respective metadata into the server resource definition on which it is hosted.
 
  
Implementations like <code>os-collection-config</code> etc. could be used for collecting software config metadata etc.
+
== Environment file ==
 +
wordpress-and-mysql-environment.yaml:
  
For synchronization purposed (e.g. in case of an explicit dependency), existing mechanisms (e.g. WaitCondition signaling) could be used under the covers, however, without surfacing them in templates.
+
resource_registry:
 +
  "Software::Wordpress": http://www.example.com/hot/software/wordpress_component.yaml
 +
  "Software::MySQL": http://www.example.com/hot/software/mysql_component.yaml

Latest revision as of 08:08, 9 December 2013

Background

This page presents a work-in-progress design for the HOT software configuration feature. It should be seen as an evolution of a previous hot-software-config proposal, but factoring in results of design discussions at the recent OpenStack summit in Hong Kong. This refined proposal is captured as a new wiki page for readability reasons. Once the design is finalized, we will consolidate the various wiki pages into a single one.

Discussions page: https://wiki.openstack.org/wiki/Talk:Heat/hot-software-config-spec

Requirements

A number of requirements have been stated during design discussions, and they are also captures in the design summit etherpad. The most important ones to be addressed by this design proposal are summarized below again.

  • Composability and re-use: It must be possible to define software components once and compose and re-use them in different contexts without duplicating definitions.
  • Separation of component definitions and deployment: It must be possible to define multiple deployments of a software component, e.g. a software component defined once must be able to be deployed on different servers in a template.
  • Software components as stateful entities: It must be possible to track state of software components, i.e. whether a software deployment is in progress, has completed, or has failed.
  • Reference to software component outputs: It must be possible to retrieve outputs (attributes) of software components.
  • Ability to express dependencies between software components: It must be possible to define dependencies between software component, e.g. that input for one component is obtained from output of another component.

High level overview

Re-usable software components are modeled as SoftwareConfig resources. Those SoftwareConfig definitions point to the actual automation to later perform software configuration (e.g. Chef, Puppet, scripts, ...) and they provide the metadata that is necessary for a generic SoftwareDeployment resource to deploy a given software on a server. The SoftwareDeployment resource represents one incarnation, i.e. one concrete use, of a software component in a template. It provides specific input parameters for that deployment, it will provide outputs produced by that deployment, and most importantly it maps the deployment to a specific target server.

It is assumed that there will be different pluggable implementations for SoftwareConfig and SoftwareDeployment - one per backend configuration tool like Chef, Puppet, scripting etc. - since each configuration tool will have specific requirements on metadata and runtime implementation. Yet, it is assumed that a lot of common behavior can be covered by generic base classes for SoftwareConfig and SoftwareDeployment so only very thin plug-ins will be needed for the various CM tools (this is ongoing design work).

The following figure shows those concepts based on a Wordpress example. It is assumed that there are Chef cookbooks for configuring the Wordpress application and MySQL. Those are referenced by two SoftwareConfig resources, along with the respective metadata for each automation. The automation plus the corresponding SoftwareConfig definitions are the re-usable entities; they are not mapped to any concrete deployment target, and they do not define specific input values. There are two SoftwareDeployment resources, one for MySQL and one for Wordpress, each mapping the deployment to a separate server. A data dependency exists between the Wordpress deployment and the MySQL deployment (see also snippets later on this page) to get endpoint information about the MySQL database for configuring the Worpress application.

HOT-software-config-overview2.png

For simple templates, it is possible to define all elements (SoftwareConfig, SoftwareDeployment and other base resources) in one template file. For more complex scenarios, and to increase composability, a subset of resources can be split into separate provider templates that can be bound via environments. This is explained in more detail and with example snippets in section Packaging for re-use as provider templates.

Software Configs

SoftwareConfig resources contain definitions of metadata for automation like Chef cookbooks, scripts, etc. along with a reference to the actual automation. Once defined, they can be mapped to one or more deployment targets (servers) by means of ServerDeployment resources (see Software Deployments). SoftwareConfig definitions are specific to the used software configuration tool, since they provide tool specific metadata. The following example shows a snippet for a Chef Software Config resource (the complete example is given in section Wordpress all-in-one Example):

resources:
  wordpress_sw_config:
    type: OS::Heat::SoftwareConfig::Chef
    properties:
      cookbook: http://www.example.com/hot/chef/wordpress.zip
      role: wordpress
      # input parameters that the chef role(s) need
      inputs:
        wp_admin_user:
          type: string
          mapping: wordpress/admin_user
        wp_admin_pw:
          type: string
          mapping: wordpress/admin_password
        db_endpoint_url:
          type: string
          mapping: wordpress/db_url
        # more input parameters ...
      # output data that the chef automation produces
      outputs:
        wp_url:
          type: string
          mapping: wordpress/url

The resource type OS::Heat::SoftwareConfig::Chef indicates that this is a Chef-specific Software Config definition. The cookbook property points to the used Chef cookbook, and the role property points to the role to be set up via this Software Config. The inputs section contains the definition of input parameters that have to be passed to Chef for configuring the role. Input parameters are defined in terms of name and type. In addition, a mapping specifies to which role attribute the respective input parameters needs to be assigned (i.e. Chef-specific metadata).

The outputs section defines attributes that can be retrieved once the software deployment has completed at runtime. Those values will be available as attributes of the corresponding SoftwareDeployment resource at runtime (see also Software Deployments).

Software Deployments

A SoftwareDeployment resource represents one concrete use of a piece of software (defined via a SoftwareConfig resource) in a template. It points to the SoftwareConfig that shall be applied to a deployment target, and it points to the actual deployment target (server). As with SoftwareConfig, it is assumed that SoftwareDeployment implementations will be specific to the used software configuration tools, since tool specific steps will have to be performed at runtime.

The following example shows a SoftwareDeployment definition for the Wordpress component defined earlier using Chef. For brevity, definitions of overall template parameters, outputs or other resources have been left out - please refer to section Wordpress all-in-one Example for the complete example:

resources:
  wordpress_sw_config:
    type: OS::Heat::SoftwareConfig::Chef
    properties:
      # ...

  wordpress_deployment:
    type: OS::Heat::SoftwareDeployment::Chef
    properties:
      apply_config: { get_resource: wordpress_sw_config }
      server: { get_resource: wp_server }
      input_values:
        wp_admin_user: { get_param: wp_admin_user }
        wp_admin_pw: { get_param: wp_admin_pw }
        # more input parameters ...

  wp_server:
    type: OS::Nova::Server
    properties:
      # ...

The wordpress_deployment resource points to the wordpress_sw_config SoftwareConfig resource and specifies that one incarnation of it shall be deployed on (applied to) server wp_server. In the input_values section of the SoftwareDeployment properties, input for the configurable parameters of the Wordpress deployment is provided, for example, by getting global template parameters specified by the user at deployment time. Those parameters map to those defined in the wordpress_sw_config resource shown earlier.

The output parameters defined under outputs in the wordpress_sw_config resource can be observed as attributes of the wordpress_deployment resource via the get_attr instrinsic function. For example, the following snippet in a HOT template would pass the URL of the deployed Wordpress application to the user as an output value:

outputs:
  wordpress_url:
    description: URL to access deployed Wordpress application
    value: { get_attr: [ wordpress_deployment, wp_url ]}


Responsibilities of the Software Deployment Resource

There are several aspects to be covered by implementations of Software Deployment resources. First of all, the resource code is responsible for injecting metadata into the referenced deployed target (server) for doing bootstrapping of the respective software config tool (Chef etc.). Furthermore, the resource is responsible for triggering deployment of the respective software (by invoking the underlying software config tool) when all dependencies are met. Upon completion of software deployment, the resource has to update its state to CREATE_COMPLETE so overall orchestration through Heat can progress (or failures have to be indicated via the appropriate failure state). Finally, attributes specified in the associated SoftwareConfig resource have to be obtained from the underlying software config tool so that uses of the get_attr can be resolved.

Dependencies between Software Deployments

Software Deployments in many cases depend on other Software Deployments. For example, the Wordpress application requires a MySQL database to be set up for storing content. There are two ways for declaring dependencies between Software Deployments: data flow based and explicit definition.

Data flow based

A data flow based dependency between two Software Deployments exists, when a property (input) of one Software Deployment is obtained from an attribute (output) of another Software Deployment. A dependency between the two SoftwareDeployment resources is enforced by the Heat engine implicitly. For example

resources:
  wordpress_deployment:
    type: OS::Heat::SoftwareDeployment::Chef
    properties:
      apply_config: { get_resource: wordpress_sw_config }
      server: { get_resource: wp_server }
      input_values:
        wp_admin_user: { get_param: wp_admin_user }
        wp_admin_pw: { get_param: wp_admin_pw }
        db_endpoint_url: { get_attr: [ mysql_deployment, db_url ] }
        # more input parameters ...

  mysql_deployment:
    type: OS::Heat::SoftwareDeployment::Chef
    properties:
      apply_config: { get_resource: mysql_sw_config }
      server: { get_resource: db_server }
      input_values:
        # input parameters for MySQL deployment ...

would introduce a dependency from wordpress_deployment to mysql_deployment since one of the properties of wordpress_deployment is set using the get_attr function refering to an attribute of the mysql_deployment resource. As a result, resource mysql_deployment must be in state CREATE_COMPLETE before processing of resource wordpress_deployment starts. The complete example is shown in section Wordpress all-in-one Example.

Explicit dependency

If no data dependency exists, but there is still a timing dependency (e.g. a process must be up before a client can connect to it), a mechanism for declaring an explicit dependency is required. This can be solved by explicitly defining dependencies of a software deployment in a depends_on clause which is a list of resource IDs of other resources that a Software Deployment depends on, for example:

resources:
  client:
    type: OS::Heat::SoftwareDeployment::Chef
    properties:
      apply_config: { get_resource: client_sw_config }
      server: { get_resource: my_server }
      input_values:
        # params ...
    depends_on:
      - get_resource: server_process1
      - get_resource: server_process2

  server_process1:
    type: OS::Heat::SoftwareDeployment::Chef
    properties:
      apply_config: { get_resource: server_process1_sw_config }
      server: { get_resource: my_server }
      input_values:
        # params ...

  server_process2:
    type: OS::Heat::SoftwareDeployment::Chef
    properties:
      apply_config: { get_resource: server_process2_sw_config }
      server: { get_resource: my_server }
      input_values:
        # params ...

  my_server:
    type: OS::Nova::Server
    properties:
      # ...

In the example above, client would depend on both server_process1 and server_process2 to be completed.


Packaging for re-use as provider templates

In descriptions given so far it was outlined how SoftwareConfig and SoftwareDeployment can be used in a HOT template to address software orchestration in Heat. For simple examples or for getting started, it is possible to put all definitions into a single template file. However, to make definitions more re-usable or when it comes to bigger, more complex scenarios, it makes sense to split definitions of software components into separate files. For example, instead of having the Software Config definition of the Wordpress application (wordpress_sw_config in examples above) with all details (pointer to Chef cookbook, definition of inputs and outputs etc.) duplicated in each template that uses Wordpress, it is better to put those definitions into one file that can be leveraged by other templates as a provider template.

One possible option is to define both the SoftwareConfig resource and the SoftwareDeployment resource for the Wordpress application in a separate template file and provide all input parameters as well as the pointer to the target server as input when using the provider template. The corresponding provider template would look like the following snippet (complete example given in section Wordpress example with re-usable provider templates):

heat_template_version: 2013-05-23

parameters:
  wp_admin_user:
    description: Username of the Wordpress admin user.
    type: string
  wp_admin_pw:
    description: Password of the Wordpress admin user.
    type: string
  db_endpoint_url:
    description: Endpoint URL of the database to be used.
    type: string
  # more software related parameters ...

  server:
    description: Reference to server onto which to install Wordpress.
    type: string

resources:
  wordpress_sw_config:
    type: OS::Heat::SoftwareConfig::Chef
    properties:
      cookbook: http://www.example.com/hot/chef/wordpress.zip
      role: wordpress
      # input parameters that the chef role(s) need
      inputs:
        # ...
      # output data that the chef automation produces
      outputs:
        # ...

  wordpress_deployment:
    type: OS::Heat::SoftwareDeployment::Chef
    properties:
      apply_config: { get_resource: wordpress_sw_config }
      server: { get_param: server }
      input_values:
        wp_admin_user: { get_param: wp_admin_user }
        wp_admin_pw: { get_param: wp_admin_pw }
        db_endpoint_url: { get_param: db_endpoint_url }
        # ...

outputs:
  wordpress_url:
    description: URL to access deployed Wordpress application
    value: { get_attr: [ wordpress_deployment, wp_url ]}

Note that even though the SoftwareDeployment resource is contained within the provider template, the definition is still re-usable since no mapping to any server is defined. A reference to the server on which the Software Deployment shall be run is provided as input parameter in the place where the provider template is used. This is achieved by having the server parameter defined in the parameters section of the template, and by having the server property of the wordpress_deployment resource be initialized with the user-provided parameter.

Note that in addition to having better re-usability of Software Config definitions in contrast to having them included in the actual template file, the approach of defining them in provider templates also offers the possibility to do richer input parameter validation, since the parameters section of a HOT template features more schema-like expressiveness through constraints that can be expressed for each input parameter.

With a re-usable definition for MySQL in a similar file, a HOT template for an actual deployment can then be composed as outlined in the following snippet:

heat_template_version: 2013-05-23

parameters:
  # parameter definitions omitted for brevity

resources:
  wordpress:
    type: Software::Wordpress
    properties:
      server: { get_resource: wp_server }
      wp_admin_user: { get_param: wp_admin_user }
      wp_admin_pw: { get_param: wp_admin_pw }
      db_endpoint_url: { get_attr: [ mysql, db_endpoint_url ] }
      db_user: { get_param: db_user }
      db_pw: { get_param: db_pw }

  wp_server:
    type: OS::Nova::Server
    properties:
      image: { get_param: image }
      flavor: { get_param: flavor }

  mysql:
    type: Software::MySQL
    properties:
      server: { get_resource: db_server }
      db_user: { get_param: db_user }
      db_pw: { get_param: db_pw }
      db_name: { get_param: db_name }

  db_server:
    type: OS::Nova::Server
    properties:
      image: { get_param: image }
      flavor: { get_param: flavor }

outputs:
  wordpress_url:
    description: URL to access deployed Wordpress application
    value: { get_attr: [ wordpress_deployment, wp_url ]}

The template above does not contain the detailed definitions of the Wordpress and MySQL Software Configs any more, but just defines two concrete uses of those software components - the wordpress resource and the mysql resource. The target server for each use, as well as specific input parameters are provided as properties to those resources.

The resource type names used for both resources, Software::Wordpress or Software::MySQL, are bound to the respective provider templates by means of environment definitions. This also provides for more flexibility, since different provider templates may be used in different environments without having to change the template. For example, there may be provider templates for software that work well on Fedora but others that work on Ubuntu.

Assuming that the definition of the Wordpress component is contained in a provider templates with name wordpress_component.yaml and the definition for MySQL is contained in a file mysql_component.yaml - both available on a server - a corresponding environment definition would look like the following:

resource_registry:
  "Software::Wordpress": http://www.example.com/hot/software/wordpress_component.yaml
  "Software::MySQL": http://www.example.com/hot/software/mysql_component.yaml

Implementation considerations

This section is still very much in progress, but more or less a collection of some thoughts for now.

Bootstrapping of software configuration tools could be done using cloud-init. The software configuration resource implementation will have to inject the respective metadata into the server resource definition on which it is hosted.

Implementations like os-collect-config etc. could be used for collecting software config metadata etc.

For synchronization purposes (e.g. in case of an explicit dependency), existing mechanisms (e.g. WaitCondition signaling) could be used under the covers, however, without surfacing them in templates.

Wordpress all-in-one Example

The following listing shows the Wordpress example referenced earlier as a complete HOT template. The template includes all definitions of Software Configs, Software Deployments, as well as server resources (thus all-in-one example). Note that the example is not meant to be 100% correct so it could be used in Heat, but it is meant to give a complete end-to-end draft of the concepts described on this wiki page.

heat_template_version: 2013-05-23

description: >
  This is an all-in-one template for deployment of Wordpress and MySQL on two servers.
  The definition of software configs for Wordpress and MySQL as well as definition for
  deployment onto servers is contained in this single template file.

parameters:
  wp_admin_user:
    description: Username of the Wordpress admin user.
    type: string
  wp_admin_pw:
    description: Password of the Wordpress admin user.
    type: string
  db_user:
    description: Username of the database admin user.
    type: string
  db_pw:
    description: Password of the database admin user.
    type: string
  db_name:
    description: Database name for the Wordpress database.
    type: string
  image:
    description: Image to be used for servers.
    type: string
  flavor:
    description: Flavor to be used for servers.
    type: string

resources:
  wordpress_sw_config:
    type: OS::Heat::SoftwareConfig::Chef
    properties:
      cookbook: http://www.example.com/hot/chef/wordpress.zip
      role: wordpress
      # input parameters that the chef role(s) need
      inputs:
        wp_admin_user:
          type: string
          mapping: wordpress/admin_user
        wp_admin_pw:
          type: string
          mapping: wordpress/admin_password
        db_endpoint_url:
          type: string
          mapping: wordpress/db_url
        db_user:
          type: string
          mapping: wordpress/db_user
        db_pw:
          type: string
          mapping: wordpress/db_password
      # output data that the chef automation produces
      outputs:
        wp_url:
          type: string
          mapping: wordpress/url

  wordpress_deployment:
    type: OS::Heat::SoftwareDeployment::Chef
    properties:
      apply_config: { get_resource: wordpress_sw_config }
      server: { get_resource: wp_server }
      input_values:
        wp_admin_user: { get_param: wp_admin_user }
        wp_admin_pw: { get_param: wp_admin_pw }
        db_endpoint_url: { get_attr: [ mysql_deployment, db_url ] }
        db_user: { get_param: db_user }
        db_pw: { get_param: db_pw }

  wp_server:
    type: OS::Nova::Server
    properties:
      image: { get_param: image }
      flavor: { get_param: flavor }

  mysql_sw_config:
    type: OS::Heat::SoftwareConfig::Chef
    properties:
      cookbook: http://www.example.com/hot/chef/mysql.zip
      role: mysql-server
      # input parameters that the chef role(s) need
      inputs:
        db_name:
          type: string
          mapping: mysql-server/db_name
        db_user:
          type: string
          mapping: mysql-server/db_user
        db_pw:
          type: string
          mapping: mysql-server/db_password
      # output data that the chef automation produces
      outputs:
        db_endpoint_url:
          type: string
          mapping: mysql-server/db_url

  mysql_deployment:
    type: OS::Heat::SoftwareDeployment::Chef
    properties:
      apply_config: { get_resource: mysql_sw_config }
      server: { get_resource: db_server }
      input_values:
        db_name: { get_param: db_name }
        db_user: { get_param: db_user }
        db_pw: { get_param: db_pw }

  db_server:
    type: OS::Nova::Server
    properties:
      image: { get_param: image }
      flavor: { get_param: flavor }

outputs:
  wordpress_url:
    description: URL to access deployed Wordpress application
    value: { get_attr: [ wordpress_deployment, wp_url ]}

Wordpress example with re-usable provider templates

In section Wordpress all-in-one Example a HOT template was shown that included all definitions in a single file. This section lists the complete definitions of the same example, but with parts split into separate HOT templates that can be used as provider templates for better re-use.

Provider template for Wordpress

wordpress_component.yaml:

heat_template_version: 2013-05-23

description: >
  This template contains the definition of a Wordpress SoftwareConfig and
  corresponding SoftwareDeployment for re-use in other templates as a HOT
  provider template.

parameters:
  wp_admin_user:
    description: Username of the Wordpress admin user.
    type: string
  wp_admin_pw:
    description: Password of the Wordpress admin user.
    type: string
  db_endpoint_url:
    description: Endpoint URL of the database to be used.
    type: string
  db_user:
    description: Username to connect to the database.
    type: string
  db_pw:
    description: Password to connect to the database.
    type: string
  server:
    description: Reference to server onto which to install Wordpress.
    type: string

resources:
  wordpress_sw_config:
    type: OS::Heat::SoftwareConfig::Chef
    properties:
      cookbook: http://www.example.com/hot/chef/wordpress.zip
      role: wordpress
      # input parameters that the chef role(s) need
      inputs:
        wp_admin_user:
          type: string
          mapping: wordpress/admin_user
        wp_admin_pw:
          type: string
          mapping: wordpress/admin_password
        db_endpoint_url:
          type: string
          mapping: wordpress/db_url
        db_user:
          type: string
          mapping: wordpress/db_user
        db_pw:
          type: string
          mapping: wordpress/db_password
      # output data that the chef automation produces
      outputs:
        wp_url:
          type: string
          mapping: wordpress/url

  wordpress_deployment:
    type: OS::Heat::SoftwareDeployment::Chef
    properties:
      apply_config: { get_resource: wordpress_sw_config }
      server: { get_param: server }
      input_values:
        wp_admin_user: { get_param: wp_admin_user }
        wp_admin_pw: { get_param: wp_admin_pw }
        db_endpoint_url: { get_param: db_endpoint_url }
        db_user: { get_param: db_user }
        db_pw: { get_param: db_pw }

outputs:
  wordpress_url:
    description: URL to access deployed Wordpress application
    value: { get_attr: [ wordpress_deployment, wp_url ]}

Provider template for MySQL

mysql_component.yaml

heat_template_version: 2013-05-23

description: >
  This template contains the definition of a MySQL SoftwareConfig and
  corresponding SoftwareDeployment for re-use in other templates as a HOT
  provider template.

parameters:
  db_user:
    description: Username of the database admin user.
    type: string
  db_pw:
    description: Password of the database admin user.
    type: string
  db_name:
    description: Database name for the Wordpress database.
    type: string
  server:
    description: Reference to server onto which to install MySQL.
    type: string

resources:
  mysql_sw_config:
    type: OS::Heat::SoftwareConfig::Chef
    properties:
      cookbook: http://www.example.com/hot/chef/mysql.zip
      role: mysql-server
      # input parameters that the chef role(s) need
      inputs:
        db_name:
          type: string
          mapping: mysql-server/db_name
        db_user:
          type: string
          mapping: mysql-server/db_user
        db_pw:
          type: string
          mapping: mysql-server/db_password
      # output data that the chef automation produces
      outputs:
        db_endpoint_url:
          type: string
          mapping: mysql-server/db_url

  mysql_deployment:
    type: OS::Heat::SoftwareDeployment::Chef
    properties:
      apply_config: { get_resource: mysql_sw_config }
      server: { get_param: server }
      input_values:
        db_name: { get_param: db_name }
        db_user: { get_param: db_user }
        db_pw: { get_param: db_pw }

outputs:
  db_endpoint_url:
    description: Endpoint URL of the MySQL database.
    value: { get_attr: [ mysql_deployment, db_endpoint_url ]}

HOT template to deploy Wordpress and MySQL on two servers

wp-with-provider-templates.yaml:

heat_template_version: 2013-05-23

description: >
  This is a template for deployment of Wordpress and MySQL on two servers. The
  definition of the software configs for Wordpress and MySQL are contained in
  separate files that are bound as provider templates via the environment.

parameters:
  wp_admin_user:
    description: Username of the Wordpress admin user.
    type: string
  wp_admin_pw:
    description: Password of the Wordpress admin user.
    type: string
  db_user:
    description: Username of the database admin user.
    type: string
  db_pw:
    description: Password of the database admin user.
    type: string
  db_name:
    description: Database name for the Wordpress database.
    type: string
  image:
    description: Image to be used for servers.
    type: string
  flavor:
    description: Flavor to be used for servers.
    type: string

resources:
  wordpress:
    type: Software::Wordpress
    properties:
      server: { get_resource: wp_server }
      wp_admin_user: { get_param: wp_admin_user }
      wp_admin_pw: { get_param: wp_admin_pw }
      db_endpoint_url: { get_attr: [ mysql, db_endpoint_url ] }
      db_user: { get_param: db_user }
      db_pw: { get_param: db_pw }

  wp_server:
    type: OS::Nova::Server
    properties:
      image: { get_param: image }
      flavor: { get_param: flavor }

  mysql:
    type: Software::MySQL
    properties:
      server: { get_resource: db_server }
      db_user: { get_param: db_user }
      db_pw: { get_param: db_pw }
      db_name: { get_param: db_name }

  db_server:
    type: OS::Nova::Server
    properties:
      image: { get_param: image }
      flavor: { get_param: flavor }

outputs:
  wordpress_url:
    description: URL to access deployed Wordpress application
    value: { get_attr: [ wordpress_deployment, wp_url ]}


Environment file

wordpress-and-mysql-environment.yaml:

resource_registry:
  "Software::Wordpress": http://www.example.com/hot/software/wordpress_component.yaml
  "Software::MySQL": http://www.example.com/hot/software/mysql_component.yaml