bigbluebutton-Github/record-and-playback/core/lib/recordandplayback.rb
Leonardo Crauss Daronco ac801cfce7 Use journald as the default logger for rap and rap services
Changed only in the main class so journald is the default and in the
scripts related to the processes in resque. Internal scripts might still
be logging to files.
2019-12-06 17:06:32 -03:00

258 lines
7.1 KiB
Ruby
Executable File

# Set encoding to utf-8
# encoding: UTF-8
#
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
#
# Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
#
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
#
path = File.expand_path(File.join(File.dirname(__FILE__), '../lib'))
$LOAD_PATH << path
require 'recordandplayback/events_archiver'
require 'recordandplayback/generators/events'
require 'recordandplayback/generators/audio'
require 'recordandplayback/generators/video'
require 'recordandplayback/generators/audio_processor'
require 'recordandplayback/generators/presentation'
require 'open4'
require 'pp'
require 'absolute_time'
require 'logger'
require 'find'
require 'rubygems'
require 'net/http'
require 'journald/logger'
module BigBlueButton
class MissingDirectoryException < RuntimeError
end
class FileNotFoundException < RuntimeError
end
class ExecutionStatus
def initialize
@output = []
@errors = []
@detailedStatus = nil
end
attr_accessor :output
attr_accessor :errors
attr_accessor :detailedStatus
def success?
@detailedStatus.success?
end
def exited?
@detailedStatus.exited?
end
def exitstatus
@detailedStatus.exitstatus
end
end
# BigBlueButton logs information about its progress.
# Replace with your own logger if you desire.
#
# @param [Logger] log your own logger
# @return [Logger] the logger you set
def self.logger=(log)
@logger = log
end
# Get BigBlueButton logger.
#
# @return [Logger]
def self.logger
return @logger if @logger
logger = Journald::Logger.new('bbb-rap')
logger.level = Logger::INFO
@logger = logger
end
def self.redis_publisher=(publisher)
@redis_publisher = publisher
end
def self.redis_publisher
return @redis_publisher
end
def self.execute(command, fail_on_error = true)
status = ExecutionStatus.new
status.detailedStatus = Open4::popen4(command) do |pid, stdin, stdout, stderr|
BigBlueButton.logger.info("Executing: #{command}")
status.output = stdout.readlines
BigBlueButton.logger.info("Output: #{Array(status.output).join} ") unless status.output.empty?
status.errors = stderr.readlines
unless status.errors.empty?
BigBlueButton.logger.error("Error: stderr: #{Array(status.errors).join}")
end
end
BigBlueButton.logger.info("Success?: #{status.success?}")
BigBlueButton.logger.info("Process exited? #{status.exited?}")
BigBlueButton.logger.info("Exit status: #{status.exitstatus}")
if status.success? == false and fail_on_error
raise "Execution failed"
end
status
end
def self.exec_ret(*command)
BigBlueButton.logger.info "Executing: #{command.join(' ')}"
IO.popen([*command, :err => [:child, :out]]) do |io|
io.each_line do |line|
BigBlueButton.logger.info line.chomp
end
end
BigBlueButton.logger.info "Exit status: #{$?.exitstatus}"
return $?.exitstatus
end
def self.exec_redirect_ret(outio, *command)
BigBlueButton.logger.info "Executing: #{command.join(' ')}"
BigBlueButton.logger.info "Sending output to #{outio}"
IO.pipe do |r, w|
pid = spawn(*command, :out => outio, :err => w)
w.close
r.each_line do |line|
BigBlueButton.logger.info line.chomp
end
Process.waitpid(pid)
BigBlueButton.logger.info "Exit status: #{$?.exitstatus}"
return $?.exitstatus
end
end
def self.hash_to_str(hash)
return PP.pp(hash, "")
end
def self.monotonic_clock()
return (AbsoluteTime.now * 1000).to_i
end
def self.download(url, output)
BigBlueButton.logger.info "Downloading #{url} to #{output}"
uri = URI.parse(url)
if ["http", "https", "ftp"].include? uri.scheme
response = Net::HTTP.start(uri.host, uri.port) {|http|
http.head(uri.request_uri)
}
unless response.is_a? Net::HTTPSuccess
raise "File not available: #{response.message}"
end
end
if uri.scheme.nil?
url = "file://" + url
uri = URI.parse(url)
end
Net::HTTP.start(uri.host, uri.port) do |http|
request = Net::HTTP::Get.new uri.request_uri
http.request request do |response|
open output, 'w' do |io|
response.read_body do |chunk|
io.write chunk
end
end
end
end
end
def self.try_download(url, output)
begin
self.download(url, output)
rescue Exception => e
BigBlueButton.logger.error "Failed to download file: #{e.to_s}"
FileUtils.rm_f output
end
end
def self.get_dir_size(dir_name)
size = 0
if FileTest.directory?(dir_name)
Find.find(dir_name) {|f| size += File.size(f)}
end
size.to_s
end
def self.add_tag_to_xml(xml_filename, parent_xpath, tag, content)
if File.exist? xml_filename
doc = Nokogiri::XML(File.open(xml_filename)) {|x| x.noblanks}
node = doc.at_xpath("#{parent_xpath}/#{tag}")
node.remove if not node.nil?
node = Nokogiri::XML::Node.new tag, doc
node.content = content
doc.at(parent_xpath) << node
xml_file = File.new(xml_filename, "w")
xml_file.write(doc.to_xml(:indent => 2))
xml_file.close
end
end
def self.add_raw_size_to_metadata(dir_name, raw_dir_name)
size = BigBlueButton.get_dir_size(raw_dir_name)
BigBlueButton.add_tag_to_xml("#{dir_name}/metadata.xml", "//recording", "raw_size", size)
end
def self.add_playback_size_to_metadata(dir_name)
size = BigBlueButton.get_dir_size(dir_name)
BigBlueButton.add_tag_to_xml("#{dir_name}/metadata.xml", "//recording/playback", "size", size)
end
def self.add_download_size_to_metadata(dir_name)
size = BigBlueButton.get_dir_size(dir_name)
BigBlueButton.add_tag_to_xml("#{dir_name}/metadata.xml", "//recording/download", "size", size)
end
def self.record_id_to_timestamp(r)
r.split("-")[1].to_i / 1000
end
def self.done_to_timestamp(r)
BigBlueButton.record_id_to_timestamp(File.basename(r, ".done"))
end
def self.read_props
return @props if @props
filepath = File.expand_path('../../scripts/bigbluebutton.yml', __FILE__)
@props = YAML::load(File.open(filepath))
end
def self.create_redis_publisher
props = BigBlueButton.read_props
redis_host = props['redis_host']
redis_port = props['redis_port']
redis_password = props['redis_password']
BigBlueButton.redis_publisher = BigBlueButton::RedisWrapper.new(redis_host, redis_port, redis_password)
end
end