class MotherBrain::Provisioner::Manager
Handles provisioning of nodes and joining them to a Chef
Server. Requests are delegated to a provisioner of the desired type or ‘Environment Factory’ by default.
Constants
- WORKER_OPTS
Attributes
Public Class Methods
@raise [Celluloid::DeadActorError] if Provisioner
Manager
has not been started
@return [Celluloid::Actor(Provisioner::Manager
)]
# File lib/mb/provisioner/manager.rb, line 13 def instance MB::Application[:provisioner_manager] or raise Celluloid::DeadActorError, "provisioner manager not running" end
# File lib/mb/provisioner/manager.rb, line 36 def initialize log.debug { "Provision Manager starting..." } @provisioner_registry = Celluloid::Registry.new @provisioner_supervisor = ProvisionerSupervisor.new_link(@provisioner_registry) Provisioner.all.each do |provisioner| @provisioner_supervisor.supervise_as(provisioner.provisioner_id, provisioner) end end
Public Instance Methods
Asynchronously destroy an environment that was created with motherbrain
@param [String] environment
name of the environment to destroy
@option options [#to_sym] :with
id of provisioner to use
# File lib/mb/provisioner/manager.rb, line 52 def async_destroy(environment, options = {}) job = Job.new(:destroy) async(:destroy, job, environment, options) job.ticket end
Asynchronously create a new environment
@param [#to_s] environment
name of the environment to create or append to
@param [MB::Provisioner::Manifest] manifest
manifest of nodes to create
@param [MB::Plugin] plugin
the plugin we are creating these nodes for
@see {#provision} for options
@return [MB::JobRecord]
a reference to the executing job
# File lib/mb/provisioner/manager.rb, line 72 def async_provision(environment, manifest, plugin, options = {}) options = options.reverse_merge(skip_bootstrap: false) job_type = options[:skip_bootstrap] ? :provision : :provision_and_bootstrap job = Job.new(job_type) async(:provision, job, environment, manifest, plugin, options) job.ticket end
Retrieve the running provisioner for the given ID. The default provisioner will be returned if nil is provided.
@param [#to_sym, nil] id ({Provisioner.default_id})
@raise [ProvisionerNotStarted]
if no provisioner is registered with the given ID
@return [MB::Provisioner::Base]
# File lib/mb/provisioner/manager.rb, line 92 def choose_provisioner(id) id ||= Provisioner.default_id unless provisioner = @provisioner_registry[id.to_sym] abort ProvisionerNotStarted.new(id) end provisioner end
Destroy an environment that was created with motherbrain
@param [MB::Job] job
a job to update with progress
@param [String] environment
name of the environment to destroy
@option options [#to_sym] :with
id of provisioner to use
# File lib/mb/provisioner/manager.rb, line 111 def destroy(job, environment, options = {}) job.report_running options = options.dup chef_synchronize(chef_environment: environment, force: options[:force]) do provision_data = ProvisionData.new(environment) provision_data.provisioners.each do |provisioner_name| provisioner = choose_provisioner(provisioner_name) job.set_status "Destroying nodes provisioned with #{provisioner_name.upcase}" provisioner.down job, environment, options end job.set_status "Removing nodes and clients from Chef" environment_manager.purge_nodes(environment) job.set_status "Destroying Chef environment #{environment}" environment_manager.destroy(environment) job.set_status "Destroying provision data" provision_data.destroy end job.report_success("Environment #{environment} destroyed") rescue => ex job.report_failure(ex) ensure job.terminate if job && job.alive? end
Create a new environment
@param [MB::Job] job
a job to update with progress
@param [String] environment
name of the environment to create or append to
@param [MB::Provisioner::Manifest] manifest
manifest of nodes to create
@param [MB::Plugin] plugin
the plugin we are creating these nodes for
@option options [String] :chef_version
version of Chef to install on the node
@option options [Hash] :component_versions (Hash.new)
Hash of components and the versions to set them to
@option options [Hash] :cookbook_versions (Hash.new)
Hash of cookbooks and the versions to set them to
@option options [Hash] :environment_attributes (Hash.new)
Hash of additional attributes to set on the environment
@option options [Boolean] :skip_bootstrap (false)
skip automatic bootstrapping of the created environment
@option options [Boolean] :force (false)
force provisioning nodes to the environment even if the environment is locked
# File lib/mb/provisioner/manager.rb, line 164 def provision(job, environment, manifest, plugin, options = {}) job.report_running("preparing to provision") options = options.reverse_merge( component_versions: Hash.new, cookbook_versions: Hash.new, environment_attributes: Hash.new, skip_bootstrap: false, force: false ) manifest.validate!(plugin) response = choose_provisioner(manifest.provisioner).up(job, environment, manifest, plugin, options) unless options[:skip_bootstrap] bootstrap_manifest = Bootstrap::Manifest.from_provisioner(response, manifest) write_bootstrap_manifest(job, environment, bootstrap_manifest, plugin) bootstrapper.bootstrap(job, environment, bootstrap_manifest, plugin, options) end job.report_success unless job.completed? rescue => ex job.report_failure(ex) ensure job.terminate if job && job.alive? end
Private Instance Methods
# File lib/mb/provisioner/manager.rb, line 207 def finalize_callback log.debug { "Provision Manager stopping..." } @provisioner_supervisor.terminate end
@param [MB::Job] job @param [String] environment @param [MB::Manifest] manifest @param [MB::Plugin] plugin
# File lib/mb/provisioner/manager.rb, line 197 def write_bootstrap_manifest(job, environment, manifest, plugin) filename = "#{plugin.name}_#{environment}_#{Time.now.to_i}.json" path = MB::FileSystem.manifests.join(filename) contents = JSON.pretty_generate(manifest.to_hash) job.set_status("Writing bootstrap manifest to #{path}") File.open(path, 'w') { |file| file.write contents } end