module Bebox class Node include Bebox::Logger include Bebox::FilesHelper include Bebox::VagrantHelper attr_accessor :environment, :project_root, :hostname, :ip, :created_at, :started_at, :finished_at def initialize(environment, project_root, hostname, ip) self.environment = environment self.project_root = project_root self.hostname = hostname self.ip = ip end # Create all files and directories related to an node def create create_hiera_template create_manifests_node create_node_checkpoint end # Delete all files and directories related to an node def remove remove_vagrant_box(self) remove_checkpoints remove_hiera_template remove_manifests_node end # List existing nodes for environment and type (nodes, prepared_nodes) def self.list(project_root, environment, node_type) Dir["#{environments_path(project_root)}/#{environment}/#{node_type}/*"].map { |f| File.basename(f, ".*") } end # Get node checkpoint parameter from the yml file def checkpoint_parameter_from_file(node_type, parameter) Bebox::Node.checkpoint_parameter_from_file(self.project_root, self.environment, self.hostname, node_type, parameter) end # Get node checkpoint parameter from the yml file def self.checkpoint_parameter_from_file(project_root, environment, hostname, node_type, parameter) node_config = YAML.load_file("#{environments_path(project_root)}/#{environment}/#{node_type}/#{hostname}.yml") node_config[parameter] end # Prepare the configured nodes def prepare started_at = DateTime.now.to_s prepare_deploy prepare_common_installation puppet_installation create_prepare_checkpoint(started_at) end # Deploy the puppet prepare directory def prepare_deploy `cd #{self.project_root} && BUNDLE_GEMFILE=Gemfile bundle exec cap #{self.environment} deploy:setup -S phase=node_prepare HOSTS=#{self.hostname}` `cd #{self.project_root} && BUNDLE_GEMFILE=Gemfile bundle exec cap #{self.environment} deploy -S phase=node_prepare HOSTS=#{self.hostname}` end # Execute through capistrano the common development installation packages def prepare_common_installation `cd #{self.project_root} && BUNDLE_GEMFILE=Gemfile bundle exec cap #{self.environment} deploy:prepare_installation:common -S phase=node_prepare HOSTS=#{self.hostname}` end # Execute through capistrano the puppet installation def puppet_installation `cd #{self.project_root} && BUNDLE_GEMFILE=Gemfile bundle exec cap #{self.environment} deploy:prepare_installation:puppet -S phase=node_prepare HOSTS=#{self.hostname}` end # Create the checkpoints for the prepared nodes def create_prepare_checkpoint(started_at) self.started_at = started_at self.finished_at = DateTime.now.to_s generate_file_from_template("#{Bebox::FilesHelper::templates_path}/node/prepared_node.yml.erb", "#{self.project_root}/.checkpoints/environments/#{self.environment}/prepared_nodes/#{self.hostname}.yml", {node: self}) end # Create the puppet hiera template file def create_hiera_template options = {ssh_key: Bebox::Project.public_ssh_key_from_file(project_root, environment), project_name: Bebox::Project.shortname_from_file(project_root)} Bebox::Provision.generate_hiera_for_steps(self.project_root, "node.yaml.erb", self.hostname, options) end # Create the node in the puppet manifests file def create_manifests_node Bebox::Provision.add_node_to_step_manifests(self.project_root, self) end # returns an Array of the Node objects for an environment # @returns Array def self.nodes_in_environment(project_root, environment, node_type) node_objects = [] nodes = Bebox::Node.list(project_root, environment, node_type) nodes.each do |hostname| ip = Bebox::Node.checkpoint_parameter_from_file(project_root, environment, hostname, node_type, 'ip') node_objects << Bebox::Node.new(environment, project_root, hostname, ip) end node_objects end # Create checkpoint for node def create_node_checkpoint # Set the creation time for the node self.created_at = DateTime.now.to_s # Create the checkpoint file from template generate_file_from_template("#{Bebox::FilesHelper::templates_path}/node/node.yml.erb", "#{project_root}/.checkpoints/environments/#{environment}/nodes/#{hostname}.yml", {node: self}) end # Remove checkpoints for node def remove_checkpoints `cd #{self.project_root} && rm -rf .checkpoints/environments/#{self.environment}/{nodes,prepared_nodes,steps/step-{0..3}}/#{self.hostname}.yml` end # Remove puppet hiera template file def remove_hiera_template Bebox::Provision.remove_hiera_for_steps(self.project_root, self.hostname) end # Remove node from puppet manifests def remove_manifests_node Bebox::Provision.remove_node_for_steps(self.project_root, self.hostname) end # Get the environments path for project def self.environments_path(project_root) "#{project_root}/.checkpoints/environments" end # Regenerate the deploy file for the environment def self.regenerate_deploy_file(project_root, environment, nodes) template_name = (environment == 'vagrant') ? 'vagrant' : "environment" generate_file_from_template("#{Bebox::FilesHelper::templates_path}/project/config/deploy/#{template_name}.erb", "#{project_root}/config/deploy/#{environment}.rb", {nodes: nodes, environment: environment}) end # Count the number of prepared nodes def prepared_nodes_count Bebox::Node.list(self.project_root, self.environment, 'prepared_nodes').count end # Return a description string for the node provision state def self.node_provision_state(project_root, environment, node) provision_state = '' checkpoint_directories = %w{nodes prepared_nodes steps/step-0 steps/step-1 steps/step-2 steps/step-3} checkpoint_directories.each do |checkpoint_directory| checkpoint_directory_path = "#{project_root}/.checkpoints/environments/#{environment}/#{checkpoint_directory}/#{node}.yml" next unless File.exist?(checkpoint_directory_path) provision_state = "#{state_from_checkpoint(checkpoint_directory)} at #{Bebox::Node.node_creation_date(project_root, environment, checkpoint_directory, node)}" end provision_state end # Get the corresponding state from checkpoint directory def self.state_from_checkpoint(checkpoint) case checkpoint when 'nodes' 'Allocated' when 'prepared_nodes' 'Prepared' when 'steps/step-0' 'Provisioned Fundamental step-0' when 'steps/step-1' 'Provisioned Users layer step-1' when 'steps/step-2' 'Provisioned Services layer step-2' when 'steps/step-3' 'Provisioned Security layer step-3' end end # Obtain the node creation_at parameter for a node def self.node_creation_date(project_root, environment, node_type, node) node_config = YAML.load_file("#{project_root}/.checkpoints/environments/#{environment}/#{node_type}/#{node}.yml") (node_type == 'nodes') ? node_config['created_at'] : node_config['finished_at'] end # Count the number of nodes in all environments def self.count_all_nodes_by_type(project_root, node_type) nodes_count = 0 environments = Bebox::Environment.list(project_root) environments.each do |environment| nodes_count += Bebox::Node.list(project_root, environment, node_type).count end nodes_count end # Restore the previous local hosts file def restore_local_hosts(project_name) `sudo cp #{local_hosts_path}/hosts_before_#{project_name} #{local_hosts_path}/hosts` `sudo rm #{local_hosts_path}/hosts_before_#{project_name}` end end end