class PhusionPassenger::AdminTools::ServerInstance

Constants

DIR_STRUCTURE_MAJOR_VERSION

If you change the structure version then don't forget to change ext/common/ServerInstanceDir.h too.

DIR_STRUCTURE_MINOR_VERSION
GENERATION_STRUCTURE_MAJOR_VERSION
GENERATION_STRUCTURE_MINOR_VERSION
STALE_TIME_THRESHOLD

Attributes

generation_path[R]
path[R]
pid[R]

Public Class Methods

for_pid(pid, options = {}) click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 136
def self.for_pid(pid, options = {})
        return list(options).find { |c| c.pid == pid }
end
list(options = {}) click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 109
def self.list(options = {})
        options = {
                :clean_stale_or_corrupted => true
        }.merge(options)
        instances = []
        
        Dir["#{AdminTools.tmpdir}/passenger.*"].each do |dir|
                next if File.basename(dir) !~ %rpassenger\.#{DIR_STRUCTURE_MAJOR_VERSION}\.(\d+)\.(\d+)\Z/
                minor = $1
                next if minor.to_i > DIR_STRUCTURE_MINOR_VERSION
                
                begin
                        instances << ServerInstance.new(dir)
                rescue StaleDirectoryError, CorruptedDirectoryError
                        if options[:clean_stale_or_corrupted] &&
                           File.stat(dir).mtime < current_time - STALE_TIME_THRESHOLD
                                log_cleaning_action(dir)
                                FileUtils.chmod_R(0700, dir) rescue nil
                                FileUtils.rm_rf(dir)
                        end
                rescue UnsupportedGenerationStructureVersionError, GenerationsAbsentError
                        # Do nothing.
                end
        end
        return instances
end
new(path) click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 140
def initialize(path)
        raise ArgumentError, "Path may not be nil." if path.nil?
        @path = path
        
        if File.exist?("#{path}/control_process.pid")
                data = File.read("#{path}/control_process.pid").strip
                @pid = data.to_i
        else
                path =~ %rpassenger\.\d+\.\d+\.(\d+)\Z/
                @pid = $1.to_i
        end
        
        generations = Dir["#{path}/generation-*"]
        if generations.empty?
                raise GenerationsAbsentError, "There are no generation subdirectories in this instance directory."
        end
        highest_generation_number = 0
        generations.each do |generation|
                File.basename(generation) =~ %r(\d+)/
                generation_number = $1.to_i
                if generation_number > highest_generation_number
                        highest_generation_number = generation_number
                end
        end
        @generation_path = "#{path}/generation-#{highest_generation_number}"
        
        if !File.exist?("#{@generation_path}/structure_version.txt")
                raise CorruptedDirectoryError, "The generation directory doesn't contain a structure version specification file."
        end
        version_data = File.read("#{@generation_path}/structure_version.txt").strip
        major, minor = version_data.split(".", 2)
        if major.nil? || minor.nil? || major !~ %r\A\d+\Z/ || minor !~ %r\A\d+\Z/
                raise CorruptedDirectoryError, "The generation directory doesn't contain a valid structure version specification file."
        end
        major = major.to_i
        minor = minor.to_i
        if major != GENERATION_STRUCTURE_MAJOR_VERSION || minor > GENERATION_STRUCTURE_MINOR_VERSION
                raise UnsupportedGenerationStructureVersionError, "Unsupported generation directory structure version."
        end
        
        if @pid == 0
                raise CorruptedDirectoryError, "Instance directory contains corrupted control_process.pid file."
        elsif !AdminTools.process_is_alive?(@pid)
                raise StaleDirectoryError, "There is no instance with PID #{@pid}."
        end
end

Public Instance Methods

analytics_log_dir() click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 239
def analytics_log_dir
        return File.read("#{@generation_path}/analytics_log_dir.txt")
rescue Errno::ENOENT
        return nil
end
backtraces() click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 249
def backtraces
        return @client.backtraces
end
connect(role_or_username, password = nil) { |self| ... } click to toggle source

Raises:

  • ArgumentError: Unsupported role

  • RoleDeniedError: The user that the current process is as is not authorized to utilize the given role.

  • EOFError: The server unexpectedly closed the connection during authentication.

  • SecurityError: The server denied our authentication credentials.

# File lib/phusion_passenger/admin_tools/server_instance.rb, line 192
def connect(role_or_username, password = nil)
        if role_or_username.is_a?(Symbol)
                case role_or_username
                when :passenger_status
                        username = "_passenger-status"
                        begin
                                filename = "#{@generation_path}/passenger-status-password.txt"
                                password = File.open(filename, "rb") do |f|
                                        f.read
                                end
                        rescue Errno::EACCES
                                raise RoleDeniedError
                        end
                else
                        raise ArgumentError, "Unsupported role #{role_or_username}"
                end
        else
                username = role_or_username
        end
        
        @client = MessageClient.new(username, password, "unix:#{@generation_path}/socket")
        begin
                yield self
        ensure
                @client.close
        end
end
global_queue_size() click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 267
def global_queue_size
        return stats.global_queue_size
end
groups() click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 271
def groups
        doc = REXML::Document.new(xml)
        
        groups = []
        doc.elements.each("info/groups/group") do |group_xml|
                group = Group.new(group_xml.elements["app_root"].text,
                        group_xml.elements["name"].text,
                        group_xml.elements["environment"].text)
                group_xml.elements.each("processes/process") do |process_xml|
                        process = Process.new(group)
                        process_xml.elements.each do |element|
                                if element.name == "server_sockets"
                                        element.elements.each("server_socket") do |server_socket|
                                                name = server_socket.elements["name"].text.to_sym
                                                address = server_socket.elements["address"].text
                                                address_type = server_socket.elements["type"].text
                                                process.server_sockets[name] = OpenStruct.new(
                                                        :address => address,
                                                        :address_type => address_type
                                                )
                                        end
                                else
                                        if process.respond_to?("#{element.name}=")
                                                if Process::INT_PROPERTIES.include?(element.name.to_sym)
                                                        value = element.text.to_i
                                                elsif Process::BOOL_PROPERTIES.include?(element.name.to_sym)
                                                        value = element.text == "true"
                                                else
                                                        value = element.text
                                                end
                                                process.send("#{element.name}=", value)
                                        end
                                end
                        end
                        group.processes << process
                end
                groups << group
        end
        return groups
end
helper_server_pid() click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 235
def helper_server_pid
        return File.read("#{@generation_path}/helper_server.pid").strip.to_i
end
processes() click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 312
def processes
        return groups.map do |group|
                group.processes
        end.flatten
end
stats() click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 257
def stats
        doc = REXML::Document.new(xml)
        stats = Stats.new
        stats.max = doc.elements["info/max"].text.to_i
        stats.count = doc.elements["info/count"].text.to_i
        stats.active = doc.elements["info/active"].text.to_i
        stats.global_queue_size = doc.elements["info/global_queue_size"].text.to_i
        return stats
end
status() click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 245
def status
        return @client.status
end
web_server_config_files() click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 224
def web_server_config_files
        config_files = File.read("#{@generation_path}/config_files.txt").split("\n")
        config_files.map! do |filename|
                filename.strip
        end
        config_files.reject do |filename|
                filename.empty?
        end
        return config_files
end
web_server_description() click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 220
def web_server_description
        return File.read("#{@generation_path}/web_server.txt")
end
xml() click to toggle source
# File lib/phusion_passenger/admin_tools/server_instance.rb, line 253
def xml
        return @client.xml
end