class CORL::Provisioner::Puppetnode

Public Class Methods

network() click to toggle source
   # File lib/CORL/provisioner/puppetnode.rb
18 def self.network
19   @@network
20 end
node() click to toggle source
   # File lib/CORL/provisioner/puppetnode.rb
22 def self.node
23   @@node
24 end
status() click to toggle source
   # File lib/CORL/provisioner/puppetnode.rb
12 def self.status
13   @@status
14 end

Public Instance Methods

add_search_path(type, resource_name) click to toggle source
    # File lib/CORL/provisioner/puppetnode.rb
213 def add_search_path(type, resource_name)
214   Config.set_options([ :all, type ], { :search => [ resource_name.to_s ] })
215 end
build_module(name, project_reference, directory, profile, environment, options = {}) click to toggle source
    # File lib/CORL/provisioner/puppetnode.rb
166 def build_module(name, project_reference, directory, profile, environment, options = {})
167   config                = Config.ensure(options)
168   module_directory      = File.join(directory, name.to_s)
169   full_module_directory = File.join(network.directory, module_directory)
170   module_project        = nil
171   success               = true
172 
173   FileUtils.rm_rf(full_module_directory) if config.get(:clean, false)
174 
175   info("Building #{blue(profile)} Puppet module #{blue(name)} at #{purple(project_reference)} into #{green(module_directory)}", { :i18n => false })
176 
177   module_project = build_config.manage(:project, extended_config(:puppet_module, {
178     :directory     => full_module_directory,
179     :url           => project_reference,
180     :create        => File.directory?(full_module_directory) ? false : true,
181     :pull          => true,
182     :internal_ip   => CORL.public_ip, # Needed for seeding Vagrant VMs
183     :manage_ignore => false
184   }))
185   unless module_project
186     warn("Puppet module #{cyan(name)} failed to initialize", { :i18n => false })
187     success = false
188   end
189   #success("Build of #{blue(profile)} #{blue(name)} finished", { :i18n => false }) if success
190   success
191 end
build_profile(name, info, package, environment, profiles, options = {}) click to toggle source
Calls superclass method
    # File lib/CORL/provisioner/puppetnode.rb
147 def build_profile(name, info, package, environment, profiles, options = {})
148   super do |processed_info|
149     package_id = id(package)
150     directory  = File.join(internal_path(build_directory), package_id.to_s, name.to_s)
151     success    = true
152 
153     #info("Building CORL profile #{blue(name)} modules into #{green(directory)}", { :i18n => false })
154 
155     if processed_info.has_key?(:modules)
156       status  = parallel(:build_module, hash(processed_info[:modules]), directory, name, environment, options)
157       success = status.values.include?(false) ? false : true
158 
159       build_config.set_location(:puppet_module, profile_id(package, name), directory) if success
160     end
161     #success("Build of profile #{blue(name)} finished", { :i18n => false }) if success
162     success
163   end
164 end
compiler() click to toggle source
   # File lib/CORL/provisioner/puppetnode.rb
77 def compiler
78   @compiler
79 end
handle(msg) click to toggle source
   # File lib/CORL/provisioner/puppetnode.rb
39 def handle(msg)
40   levels = {
41     :emerg => { :name => 'emergency', :send => :error },
42     :alert => { :name => 'alert', :send => :error },
43     :crit => { :name => 'critical', :send => :error },
44     :err => { :name => 'error', :send => :error },
45     :warning => { :name => 'warning', :send => :warn },
46     :notice => { :name => 'notice', :send => :success },
47     :info => { :name => 'info', :send => :info },
48     :debug => { :name => 'debug', :send => :info }
49   }
50   str = msg.respond_to?(:multiline) ? msg.multiline : msg.to_s
51   str = msg.source == "Puppet" ? str : "#{CORL.blue(msg.source)}: #{str}"
52   level = levels[msg.level]
53 
54   if [ :error ].include?(level[:send])
55     ::CORL::Provisioner::Puppetnode.status[name] = 111
56   end
57 
58   CORL.ui_group("puppetnode::#{name}(#{CORL.yellow(level[:name])})", :cyan) do |ui|
59     ui.send(level[:send], str)
60   end
61   puts caller if level[:send] == :error && [ :warn, :error ].include?(CORL.log_level)
62 end
import(files, options = {}) click to toggle source
    # File lib/CORL/provisioner/puppetnode.rb
204 def import(files, options = {})
205   Util::Puppet.import(files, Config.ensure(options).defaults({
206     :puppet_scope       => scope,
207     :puppet_import_base => network.directory
208   }))
209 end
lookup(property, default = nil, options = {}) click to toggle source
    # File lib/CORL/provisioner/puppetnode.rb
195 def lookup(property, default = nil, options = {})
196   Util::Puppet.lookup(property, default, Config.ensure(options).defaults({
197     :provisioner  => :puppetnode,
198     :puppet_scope => scope
199   }))
200 end
normalize(reload) click to toggle source
Calls superclass method
   # File lib/CORL/provisioner/puppetnode.rb
29 def normalize(reload)
30   super do
31     require 'puppet'
32     require 'puppet/configurer'
33 
34     if [ :debug, :info, :warn ].include? CORL.log_level
35       Puppet.debug = true
36     end
37     unless reload
38       Puppet::Util::Log.newdesttype id do
39         def handle(msg)
40           levels = {
41             :emerg => { :name => 'emergency', :send => :error },
42             :alert => { :name => 'alert', :send => :error },
43             :crit => { :name => 'critical', :send => :error },
44             :err => { :name => 'error', :send => :error },
45             :warning => { :name => 'warning', :send => :warn },
46             :notice => { :name => 'notice', :send => :success },
47             :info => { :name => 'info', :send => :info },
48             :debug => { :name => 'debug', :send => :info }
49           }
50           str = msg.respond_to?(:multiline) ? msg.multiline : msg.to_s
51           str = msg.source == "Puppet" ? str : "#{CORL.blue(msg.source)}: #{str}"
52           level = levels[msg.level]
53 
54           if [ :error ].include?(level[:send])
55             ::CORL::Provisioner::Puppetnode.status[name] = 111
56           end
57 
58           CORL.ui_group("puppetnode::#{name}(#{CORL.yellow(level[:name])})", :cyan) do |ui|
59             ui.send(level[:send], str)
60           end
61           puts caller if level[:send] == :error && [ :warn, :error ].include?(CORL.log_level)
62         end
63       end
64     end
65   end
66 end
provision(node, profiles, options = {}) click to toggle source
Calls superclass method
    # File lib/CORL/provisioner/puppetnode.rb
219 def provision(node, profiles, options = {})
220   super do |processed_profiles, config|
221     locations = build_locations(node)
222     success   = true
223 
224     include_location = lambda do |type, parameters = {}, add_search_path = false|
225       classes = {}
226 
227       locations[:package].keys.reverse.each do |name|
228         package_directory = locations[:package][name]
229         type_gateway      = File.join(network.directory, package_directory, "#{type}.pp")
230         resource_name     = resource([ name, type ])
231 
232         add_search_path(type, resource_name) if add_search_path
233 
234         if File.exists?(type_gateway)
235           import(type_gateway)
236           classes[resource_name] = parameters
237         end
238 
239         type_directory = File.join(network.directory, package_directory, type.to_s)
240         Dir.glob(File.join(type_directory, '*.pp')).each do |file|
241           resource_name = resource([ name, type, File.basename(file).gsub('.pp', '') ])
242           import(file)
243           classes[resource_name] = parameters
244         end
245       end
246 
247       type_gateway = File.join(directory, "#{type}.pp")
248       resource_name = resource([ plugin_name, type ])
249 
250       add_search_path(type, resource_name) if add_search_path
251 
252       if File.exists?(type_gateway)
253         import(type_gateway)
254         classes[resource_name] = parameters
255       end
256 
257       type_directory = File.join(directory, type.to_s)
258 
259       if File.directory?(type_directory)
260         Dir.glob(File.join(type_directory, '*.pp')).each do |file|
261           resource_name = resource([ plugin_name, type, File.basename(file).gsub('.pp', '') ])
262           import(file)
263           classes[resource_name] = parameters
264         end
265       end
266       classes
267     end
268 
269     @@puppet_lock.synchronize do
270       begin
271         info("Starting catalog generation at #{Time.now.to_s}", { :i18n => false })
272 
273         @@status[id] = code.success
274         @@network    = network
275         @@node       = node
276 
277         start_time        = Time.now
278         apply_environment = init_puppet(node, processed_profiles)
279 
280         if apply_environment.nil?
281           success = false
282         else
283           Puppet.override(:environments => Puppet::Environments::Static.new(apply_environment)) do
284             puppet_node = get_puppet_node(apply_environment.name)
285             @compiler   = Puppet::Parser::Compiler.new(puppet_node)
286 
287             # Register Puppet module plugins
288             register
289 
290             # Include defaults
291             classes = include_location.call(:default, {}, true)
292 
293             # Import needed profiles
294             include_location.call(:profiles, {}, false)
295 
296             processed_profiles.each do |profile|
297               classes[profile.to_s] = { :require => 'Anchor[profile_start]' }
298             end
299 
300             puppet_node.classes = classes
301 
302             # Compile catalog
303             compiler.compile
304 
305             catalog = compiler.catalog.to_ral
306             catalog.finalize
307             catalog.retrieval_duration = Time.now - start_time
308 
309             unless config.get(:dry_run, false)
310               info("\n", { :prefix => false, :i18n => false })
311               info("Starting configuration run at #{Time.now.to_s}", { :i18n => false })
312 
313               # Configure the machine
314               Puppet.push_context({ :current_environment => apply_environment }, "CORL environment for configurer transaction")
315 
316               configurer = Puppet::Configurer.new
317               if ! configurer.run(:catalog => catalog, :pluginsync => false)
318                 success = false
319               end
320             end
321           end
322         end
323 
324       rescue Exception => error
325         if [ :debug, :info, :warn, :error ].include? CORL.log_level
326           logger.error("Puppetnode provisioner experienced an error:")
327           logger.error(error.inspect)
328           logger.error(error.message)
329           logger.error(Util::Data.to_yaml(error.backtrace))
330         end
331         Puppet.log_exception(error)
332         success = false
333       end
334     end
335 
336     success = false if @@status[id] != code.success
337     success
338   end
339 end
register(options = {}) click to toggle source
   # File lib/CORL/provisioner/puppetnode.rb
70 def register(options = {})
71   Util::Puppet.register_plugins(Config.ensure(options).defaults({ :puppet_scope => scope }))
72 end
scope() click to toggle source
   # File lib/CORL/provisioner/puppetnode.rb
83 def scope
84   return compiler.topscope if compiler
85   nil
86 end

Protected Instance Methods

ensure_environment(node) click to toggle source
    # File lib/CORL/provisioner/puppetnode.rb
344 def ensure_environment(node)
345   base_directory = Puppet[:environmentpath]
346   environment    = node.lookup(:corl_environment)
347 
348   if environment.nil?
349     environment = node.lookup(:environment)
350 
351     if environment.nil?
352       error("Environment facts 'corl_environment' or 'environment' must be set to provision", { :i18n => false })
353       return []
354     end
355   end
356 
357   env_directory = File.join(base_directory, environment)
358 
359   FileUtils.mkdir_p(env_directory)
360   FileUtils.mkdir_p(File.join(env_directory, 'manifests'))
361   FileUtils.mkdir_p(File.join(env_directory, 'modules'))
362   [ environment, env_directory ]
363 end
get_puppet_node(environment) click to toggle source
    # File lib/CORL/provisioner/puppetnode.rb
134 def get_puppet_node(environment)
135   Puppet[:node_name_value] = id.to_s
136 
137   puppet_node = Puppet::Node.indirection.find(id.to_s, :environment => environment)
138 
139   puppet_node.merge(string_map(@@node.facts))
140   puppet_node
141 end
init_puppet(node, profiles) click to toggle source
    # File lib/CORL/provisioner/puppetnode.rb
 91 def init_puppet(node, profiles)
 92   Puppet.initialize_settings
 93 
 94   apply_environment = nil
 95   locations         = build_locations(node)
 96 
 97   environment, environment_directory = ensure_environment(node)
 98 
 99   return nil unless environment
100 
101   Puppet::Util::Log.newdestination(id)
102   Puppet::Transaction::Report.indirection.cache_class = :yaml
103 
104   Puppet[:graph] = true if CORL.log_level == :error
105 
106   Puppet[:node_terminus]         = :plain
107   Puppet[:data_binding_terminus] = :corl
108   Puppet[:default_file_terminus] = :file_server
109 
110   unless profiles.empty?
111     modulepath = profiles.collect do |profile|
112       profile_path      = locations[:puppet_module][profile.to_sym]
113       profile_directory = nil
114       profile_directory = File.join(network.directory, profile_path) if profile_path
115       profile_directory && File.directory?(profile_directory) ? profile_directory : nil
116     end.compact
117   end
118 
119   if manifest = gateway
120     if manifest.match(/^packages\/.*/)
121       manifest = File.join(network.build_directory, manifest)
122     else
123       manifest = File.join(network.directory, directory, manifest)
124     end
125   end
126 
127   Puppet[:environment] = environment
128   Puppet::Node::Environment.create(environment.to_sym, modulepath, manifest)
129 end