Here's an updated ActiveRecord model for adding in support for Services. It's not complete, but it should reflect the specific object types, attributes, and associations needed for Services. A few inline notes are included as comments below. Updated to restore Template->Service association and to add the concept of specifying missing config parameters at runtime (i.e. with the depoyment/instance) Still an open question is the approach to managing the package list associated with the service. Potentially, we need this in two places: 1) the package (and package group) list passed to image factory in the 'build' operation 2) the package dep list included in the puppet manifest/service config scripts What we'd like to avoid is having to manage two separate package lists, so one of these will need to be generated from the other. So again, we've got two options: 1) Manage the package list as a custom package group in pulp and generate a puppet recipe snippet that includes this as a dependency list whenever we send the puppet script content to audrey 2) Manage the package list as a puppet dependency list and automatically append these packages to the list of packages chosen explicitly by the user in the image builder UI. The model below assumes option 1) above, but again, at the moment it's still an open question. # no changes here for services unless we add an explicit # relationship to Service -- for now we only know this # indirectly as the Service package group will be included # in the template's package list class Template < ActiveRecord::Base has_many :images has_many :instances has_and_belongs_to_many :assemblies has_and_belongs_to_many :services end # Updated Deployable association to indicate that the configured # services are attached to the Deployable->Assembly relationship class Assembly < ActiveRecord::Base has_many :instances has_and_belongs_to_many :templates has_many :deployable_assemblies has_many :deployables, :through => :deployable_assemblies end class Deployable < ActiveRecord::Base has_many :deployments has_and_belongs_to_many :deployables has_many :deployable_assemblies has_many :assemblies, :through => :deployable_assemblies end class DeployableAssembly < ActiveRecord::Base belongs_to :assembly belongs_to :deployable has_many :configured_services, :dependent => :destroy end class CreateDeployableAssemblies < ActiveRecord::Migration def self.up create_table :deployable_assemblies do |t| t.string :name # optional -- use assembly name if blank t.integer :assembly_id t.integer :deployable_id end end end # a Service is a collection of packages (in a package group), # configuration scripts (puppet for now), and named configuration # parameters used to describe a service. This is the service "in # general", rather than connected to a specific # deployable/template. For the moment, a service is only valid for a # single Base OS, Version, and Architecture. If the same service needs # to exist on more than one (say Fedora 14 x86_64 and RHEL6.1 i386), # then two independent services must be created. class Service < ActiveRecord::Base has_many :service_config_scripts, :dependent => :destroy has_many :service_params, :dependent => :destroy has_and_belongs_to_many :templates has_many :configured_services, :dependent => :destroy end class CreateServices < ActiveRecord::Migration def self.up create_table :services do |t| t.string :name t.string :platform t.string :platform_version t.string :architecture # FIXME: how are we actually referencing package group? t.string :package_group end end end # A configuration script attached to a Service. For now we only # support a script_type of 'puppet'. class ServiceConfigScript < ActiveRecord::Base belongs_to :service validates_presence_of :name validates_presence_of :script_type validates_presence_of :script_content end class CreateServiceConfigScripts < ActiveRecord::Migration def self.up create_table :service_config_scripts do |t| t.string :name t.integer :service_id t.string :script_type #'puppet', etc t.text :script_content end end end # A parameter associated with a service. This doesn't hold the value # for a particular instance, but it stores the name and type (and # whether it's required). class ServiceParam < ActiveRecord::Base belongs_to :service validates_presence_of :name has_many :service_param_values # value_type: fixed or compute-from-instance; # for fixed 'value' in associated ServiceParamValue objects is actual value # for compute-from-instance value is key end class CreateServiceParams < ActiveRecord::Migration def self.up create_table :service_params do |t| t.string :name t.integer :service_id t.string :value_type t.boolean :is_required, :default => true end end end # A particular service attached to an assembly/template in the context # of a deployable. This references a Service object and fills in the # ServiceParams with actual values. class ConfiguredService < ActiveRecord::Base belongs_to :service belongs_to :deployable_assembly has_many :service_params has_many :launched_services end class CreateConfiguredServices < ActiveRecord::Migration def self.up create_table :configured_services do |t| t.integer :service_id t.integer :deployable_assembly_id end end end # Filled-in value for ServiceParam class ServiceParamValue < ActiveRecord::Base # can be either ConfiguredService or LaunchedService belongs_to :service_obj, :polymorphic => true belongs_to :configured_service belongs_to :service_param validates_presence_of :value # value_type: fixed or compute-from-instance; # for fixed 'value' is actual value # for compute-from-instance value is key end class CreateServiceParams < ActiveRecord::Migration def self.up create_table :service_params do |t| t.integer :service_obj_id t.integer :service_obj_type t.integer :service_param_id t.string :value end end end class Deployment < ActiveRecord::Base belongs_to :deployable has_many :instances end class Instance < ActiveRecord::Base belongs_to :deployment belongs_to :assembly has_many :launched_services end # A particular service attached to an instance. This references a # ConfiguredService object on the appropriate DeployableAssembly for # the appropriate instance and fills in any ServiceParamValues omitted # in the ConfiguredService. class LaunchedService < ActiveRecord::Base belongs_to :configured_service belongs_to :instance has_many :service_params end class CreateLaunchedServices < ActiveRecord::Migration def self.up create_table :launched_services do |t| t.integer :configured_service_id t.integer :instance_id end end end