Class BoxGrinder::Appliance
In: lib/boxgrinder-build/appliance.rb
lib/boxgrinder-build/appliance.rb
Parent: Object

Methods

Attributes

appliance_config  [R] 
appliance_config  [R] 
plugin_chain  [R] 
plugin_chain  [R] 

Public Class methods

[Source]

    # File lib/boxgrinder-build/appliance.rb, line 34
34:     def initialize(appliance_definition, config = Config.new, options = {})
35:       @appliance_definition = appliance_definition
36:       @config = config
37:       @log = options[:log] || LogHelper.new(:level => @config.log_level)
38:     end

[Source]

    # File lib/boxgrinder-build/appliance.rb, line 34
34:     def initialize(appliance_definition, config = Config.new, options = {})
35:       @appliance_definition = appliance_definition
36:       @config = config
37:       @log = options[:log] || LogHelper.new(:level => @config.log_level)
38:     end

Public Instance methods

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 188
188:     def change_user(u, g)
189:       begin
190:         if Process::Sys.respond_to?(:setresgid) && Process::Sys.respond_to?(:setresuid)
191:           Process::Sys.setresgid(g, g, g)
192:           Process::Sys.setresuid(u, u, u)
193:           return
194:         end
195:       rescue NotImplementedError
196:       end
197: 
198:       begin
199:         # JRuby doesn't support saved ids, use this instead.
200:         Process.gid = g
201:         Process.egid = g
202:         Process.uid = u
203:         Process.euid = u
204:       rescue NotImplementedError
205:       end
206:     end

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 188
188:     def change_user(u, g)
189:       begin
190:         if Process::Sys.respond_to?(:setresgid) && Process::Sys.respond_to?(:setresuid)
191:           Process::Sys.setresgid(g, g, g)
192:           Process::Sys.setresuid(u, u, u)
193:           return
194:         end
195:       rescue NotImplementedError
196:       end
197: 
198:       begin
199:         # JRuby doesn't support saved ids, use this instead.
200:         Process.gid = g
201:         Process.egid = g
202:         Process.uid = u
203:         Process.euid = u
204:       rescue NotImplementedError
205:       end
206:     end

This creates the appliance by executing the plugin chain.

Definition is read and validated. Afterwards a plugin chain is created and every plugin in the chain is initialized and validated. The next step is the execution of the plugin chain, step by step.

Below you can find the whole process of bootstraping a plugin.

  Call            Scope
  ------------------------------------------
  initialize      required, internal
  init            required, internal
  after_init      optional, user implemented
  validate        optional, user implemented
  after_validate  optional, user implemented
  execute         required, user implemented
  after_execute   optional, user implemented

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 142
142:     def create
143:       @log.debug "Launching new build..."
144:       @log.trace "Used configuration: #{@config.to_yaml.gsub(/(\S*(key|account|cert|username|host|password)\S*).*:(.*)/, '\1' + ": <REDACTED>")}"
145: 
146:       # Let's load all plugins first
147:       PluginHelper.new(@config, :log => @log).load_plugins
148:       read_definition
149:       validate_definition
150:       initialize_plugins
151: 
152:       remove_old_builds if @config.force
153: 
154:       execute_plugin_chain
155: 
156:       self
157:     end

This creates the appliance by executing the plugin chain.

Definition is read and validated. Afterwards a plugin chain is created and every plugin in the chain is initialized and validated. The next step is the execution of the plugin chain, step by step.

Below you can find the whole process of bootstraping a plugin.

  Call            Scope
  ------------------------------------------
  initialize      required, internal
  init            required, internal
  after_init      optional, user implemented
  validate        optional, user implemented
  after_validate  optional, user implemented
  execute         required, user implemented
  after_execute   optional, user implemented

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 142
142:     def create
143:       @log.debug "Launching new build..."
144:       @log.trace "Used configuration: #{@config.to_yaml.gsub(/(\S*(key|account|cert|username|host|password)\S*).*:(.*)/, '\1' + ": <REDACTED>")}"
145: 
146:       # Let's load all plugins first
147:       PluginHelper.new(@config, :log => @log).load_plugins
148:       read_definition
149:       validate_definition
150:       initialize_plugins
151: 
152:       remove_old_builds if @config.force
153: 
154:       execute_plugin_chain
155: 
156:       self
157:     end

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 163
163:     def delivery_selected?
164:       !(@config.delivery == :none or @config.delivery.to_s.empty? == nil)
165:     end

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 163
163:     def delivery_selected?
164:       !(@config.delivery == :none or @config.delivery.to_s.empty? == nil)
165:     end

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 167
167:     def execute_plugin(plugin, param = nil)
168:       if plugin.deliverables_exists?
169:         @log.info "Deliverables for #{plugin.plugin_info[:name]} #{plugin.plugin_info[:type]} plugin exists, skipping."
170:       else
171:         @log.debug "Executing #{plugin.plugin_info[:type]} plugin..."
172: 
173:         # Actually run the plugin
174:         param.nil? ? plugin.run : plugin.run(param)
175: 
176:         # Run after_execute callback, if implemented
177:         plugin.after_execute if plugin.respond_to?(:after_execute)
178: 
179:         @log.debug "#{plugin.plugin_info[:type].to_s.capitalize} plugin executed."
180:       end
181:       if plugin.plugin_info[:type] == :os
182:         FileUtils.chown_R(@config.uid, @config.gid, File.join(@config.dir.root, @config.dir.build))
183:         @log.debug "Lowering from root to user."
184:         change_user(@config.uid, @config.gid)
185:       end
186:     end

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 167
167:     def execute_plugin(plugin, param = nil)
168:       if plugin.deliverables_exists?
169:         @log.info "Deliverables for #{plugin.plugin_info[:name]} #{plugin.plugin_info[:type]} plugin exists, skipping."
170:       else
171:         @log.debug "Executing #{plugin.plugin_info[:type]} plugin..."
172: 
173:         # Actually run the plugin
174:         param.nil? ? plugin.run : plugin.run(param)
175: 
176:         # Run after_execute callback, if implemented
177:         plugin.after_execute if plugin.respond_to?(:after_execute)
178: 
179:         @log.debug "#{plugin.plugin_info[:type].to_s.capitalize} plugin executed."
180:       end
181:       if plugin.plugin_info[:type] == :os
182:         FileUtils.chown_R(@config.uid, @config.gid, File.join(@config.dir.root, @config.dir.build))
183:         @log.debug "Lowering from root to user."
184:         change_user(@config.uid, @config.gid)
185:       end
186:     end

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 119
119:     def execute_plugin_chain
120:       @log.info "Building '#{@appliance_config.name}' appliance for #{@appliance_config.hardware.arch} architecture."
121:       @plugin_chain.each { |p| execute_plugin(p[:plugin], p[:param]) }
122:     end

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 119
119:     def execute_plugin_chain
120:       @log.info "Building '#{@appliance_config.name}' appliance for #{@appliance_config.hardware.arch} architecture."
121:       @plugin_chain.each { |p| execute_plugin(p[:plugin], p[:param]) }
122:     end

Initializes the plugin by executing init, after_init, validate and after_validate methods.

We can be sure only for init method because it is implemented internally in base-plugin.rb, for all other methods we need to check if they exist.

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 85
 85:     def initialize_plugin(plugin, plugin_info, options = {})
 86:       options = {
 87:         :log => @log
 88:       }.merge(options)
 89: 
 90:       unless @plugin_chain.empty?
 91:         options.merge!(:previous_plugin => @plugin_chain.last[:plugin])
 92:       end
 93: 
 94:       plugin.init(@config, @appliance_config, plugin_info, options)
 95: 
 96:       # Execute callbacks if implemented
 97:       #
 98:       # Order is very important
 99:       [:after_init, :validate, :after_validate].each do |callback|
100:         plugin.send(callback) if plugin.respond_to?(callback)
101:       end
102: 
103:       param = nil
104: 
105:       # For operating system plugins we need to inject appliance definition.
106:       if plugin_info[:type] == :os
107:         param = @appliance_definition
108:       end
109: 
110:       @plugin_chain << {:plugin => plugin, :param => param}
111:     end

Initializes the plugin by executing init, after_init, validate and after_validate methods.

We can be sure only for init method because it is implemented internally in base-plugin.rb, for all other methods we need to check if they exist.

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 85
 85:     def initialize_plugin(plugin, plugin_info, options = {})
 86:       options = {
 87:         :log => @log
 88:       }.merge(options)
 89: 
 90:       unless @plugin_chain.empty?
 91:         options.merge!(:previous_plugin => @plugin_chain.last[:plugin])
 92:       end
 93: 
 94:       plugin.init(@config, @appliance_config, plugin_info, options)
 95: 
 96:       # Execute callbacks if implemented
 97:       #
 98:       # Order is very important
 99:       [:after_init, :validate, :after_validate].each do |callback|
100:         plugin.send(callback) if plugin.respond_to?(callback)
101:       end
102: 
103:       param = nil
104: 
105:       # For operating system plugins we need to inject appliance definition.
106:       if plugin_info[:type] == :os
107:         param = @appliance_definition
108:       end
109: 
110:       @plugin_chain << {:plugin => plugin, :param => param}
111:     end

Here we initialize all required plugins and create a plugin chain. Initialization involves also plugin configuration validation for specified plugin type.

[Source]

    # File lib/boxgrinder-build/appliance.rb, line 62
62:     def initialize_plugins
63:       @plugin_chain = []
64: 
65:       os_plugin, os_plugin_info = PluginManager.instance.initialize_plugin(:os, @appliance_config.os.name.to_sym)
66:       initialize_plugin(os_plugin, os_plugin_info)
67: 
68:       if platform_selected?
69:         platform_plugin, platform_plugin_info = PluginManager.instance.initialize_plugin(:platform, @config.platform)
70:         initialize_plugin(platform_plugin, platform_plugin_info)
71:       end
72: 
73:       if delivery_selected?
74:         delivery_plugin, delivery_plugin_info = PluginManager.instance.initialize_plugin(:delivery, @config.delivery)
75:         # Here we need to specify additionaly the type of the plugin, as some delivery plugins
76:         # can have multiple types of delivery implemented. See s3-plugin.rb for example.
77:         initialize_plugin(delivery_plugin, delivery_plugin_info, :type => @config.delivery)
78:       end
79:     end

Here we initialize all required plugins and create a plugin chain. Initialization involves also plugin configuration validation for specified plugin type.

[Source]

    # File lib/boxgrinder-build/appliance.rb, line 62
62:     def initialize_plugins
63:       @plugin_chain = []
64: 
65:       os_plugin, os_plugin_info = PluginManager.instance.initialize_plugin(:os, @appliance_config.os.name.to_sym)
66:       initialize_plugin(os_plugin, os_plugin_info)
67: 
68:       if platform_selected?
69:         platform_plugin, platform_plugin_info = PluginManager.instance.initialize_plugin(:platform, @config.platform)
70:         initialize_plugin(platform_plugin, platform_plugin_info)
71:       end
72: 
73:       if delivery_selected?
74:         delivery_plugin, delivery_plugin_info = PluginManager.instance.initialize_plugin(:delivery, @config.delivery)
75:         # Here we need to specify additionaly the type of the plugin, as some delivery plugins
76:         # can have multiple types of delivery implemented. See s3-plugin.rb for example.
77:         initialize_plugin(delivery_plugin, delivery_plugin_info, :type => @config.delivery)
78:       end
79:     end

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 159
159:     def platform_selected?
160:       !(@config.platform == :none or @config.platform.to_s.empty? == nil)
161:     end

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 159
159:     def platform_selected?
160:       !(@config.platform == :none or @config.platform.to_s.empty? == nil)
161:     end

[Source]

    # File lib/boxgrinder-build/appliance.rb, line 40
40:     def read_definition
41:       appliance_helper = ApplianceDefinitionHelper.new(:log => @log)
42:       appliance_helper.read_definitions(@appliance_definition)
43: 
44:       appliance_configs = appliance_helper.appliance_configs
45:       appliance_config = appliance_configs.first
46: 
47:       raise ValidationError, "Ensure your appliance definition file has a '.appl' extension: #{File.basename(@appliance_definition)}." if appliance_config.nil?
48: 
49:       appliance_config_helper = ApplianceConfigHelper.new(appliance_configs)
50:       @appliance_config = appliance_config_helper.merge(appliance_config.clone.init_arch).initialize_paths
51:     end

[Source]

    # File lib/boxgrinder-build/appliance.rb, line 40
40:     def read_definition
41:       appliance_helper = ApplianceDefinitionHelper.new(:log => @log)
42:       appliance_helper.read_definitions(@appliance_definition)
43: 
44:       appliance_configs = appliance_helper.appliance_configs
45:       appliance_config = appliance_configs.first
46: 
47:       raise ValidationError, "Ensure your appliance definition file has a '.appl' extension: #{File.basename(@appliance_definition)}." if appliance_config.nil?
48: 
49:       appliance_config_helper = ApplianceConfigHelper.new(appliance_configs)
50:       @appliance_config = appliance_config_helper.merge(appliance_config.clone.init_arch).initialize_paths
51:     end

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 113
113:     def remove_old_builds
114:       @log.info "Removing previous builds for #{@appliance_config.name} appliance..."
115:       FileUtils.rm_rf(@appliance_config.path.build)
116:       @log.debug "Previous builds removed."
117:     end

[Source]

     # File lib/boxgrinder-build/appliance.rb, line 113
113:     def remove_old_builds
114:       @log.info "Removing previous builds for #{@appliance_config.name} appliance..."
115:       FileUtils.rm_rf(@appliance_config.path.build)
116:       @log.debug "Previous builds removed."
117:     end

[Source]

    # File lib/boxgrinder-build/appliance.rb, line 53
53:     def validate_definition
54:       os_plugin = PluginManager.instance.plugins[:os][@appliance_config.os.name.to_sym]
55: 
56:       raise "Unsupported operating system selected: #{@appliance_config.os.name}. Make sure you have installed right operating system plugin, see http://boxgrinder.org/tutorials/boxgrinder-build-plugins/#Operating_system_plugins. Supported OSes are: #{PluginManager.instance.plugins[:os].keys.join(", ")}" if os_plugin.nil?
57:       raise "Unsupported operating system version selected: #{@appliance_config.os.version}. Supported versions are: #{os_plugin[:versions].join(", ")}" unless @appliance_config.os.version.nil? or os_plugin[:versions].include?(@appliance_config.os.version)
58:     end

[Source]

    # File lib/boxgrinder-build/appliance.rb, line 53
53:     def validate_definition
54:       os_plugin = PluginManager.instance.plugins[:os][@appliance_config.os.name.to_sym]
55: 
56:       raise "Unsupported operating system selected: #{@appliance_config.os.name}. Make sure you have installed right operating system plugin, see http://boxgrinder.org/tutorials/boxgrinder-build-plugins/#Operating_system_plugins. Supported OSes are: #{PluginManager.instance.plugins[:os].keys.join(", ")}" if os_plugin.nil?
57:       raise "Unsupported operating system version selected: #{@appliance_config.os.version}. Supported versions are: #{os_plugin[:versions].join(", ")}" unless @appliance_config.os.version.nil? or os_plugin[:versions].include?(@appliance_config.os.version)
58:     end

[Validate]