csd 0.1.18 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/ai +22 -1
- data/bin/ttai +47 -0
- data/csd.gemspec +15 -6
- data/lib/csd.rb +75 -16
- data/lib/csd/application/decklink/base.rb +2 -2
- data/lib/csd/application/default.rb +2 -3
- data/lib/csd/application/default/base.rb +5 -2
- data/lib/csd/application/i2conf.rb +28 -0
- data/lib/csd/application/i2conf/about.yml +8 -0
- data/lib/csd/application/i2conf/base.rb +215 -0
- data/lib/csd/application/i2conf/config_example.rb +22 -0
- data/lib/csd/application/i2conf/options/common.rb +11 -0
- data/lib/csd/application/i2conf/options/common_defaults.rb +4 -0
- data/lib/csd/application/i2conf/options/install.rb +10 -0
- data/lib/csd/application/i2conf/options/install_defaults.rb +4 -0
- data/lib/csd/application/minisip.rb +8 -12
- data/lib/csd/application/minisip/about.yml +12 -4
- data/lib/csd/application/minisip/base.rb +40 -1
- data/lib/csd/application/minisip/component.rb +2 -0
- data/lib/csd/application/minisip/component/core.rb +13 -6
- data/lib/csd/application/minisip/component/gnome.rb +1 -0
- data/lib/csd/application/minisip/component/network.rb +95 -0
- data/lib/csd/application/minisip/component/plugins.rb +1 -1
- data/lib/csd/application/minisip/options/{compile.rb → install.rb} +4 -0
- data/lib/csd/application/minisip/options/{compile_defaults.rb → install_defaults.rb} +2 -1
- data/lib/csd/application/minisip/phonebook_example.rb +41 -12
- data/lib/csd/application/minisip/unix.rb +24 -17
- data/lib/csd/application/minisip/unix/linux/debian.rb +13 -5
- data/lib/csd/application/minisip/unix/linux/debian/ubuntu10.rb +3 -2
- data/lib/csd/applications.rb +1 -1
- data/lib/csd/commands.rb +23 -5
- data/lib/csd/extensions/gem/platform.rb +12 -0
- data/lib/csd/options_parser.rb +31 -11
- data/test/application/test_minisip.rb +63 -6
- data/test/functional/test_options.rb +82 -3
- metadata +19 -8
data/.gitignore
CHANGED
data/Rakefile
CHANGED
@@ -25,7 +25,7 @@ Jeweler::Tasks.new do |gemspec|
|
|
25
25
|
gemspec.email = "mtoday11@gmail.com"
|
26
26
|
gemspec.homepage = "http://github.com/csd/csd"
|
27
27
|
gemspec.authors = ["Technology Transfer Alliance Team"]
|
28
|
-
gemspec.executables = ['ai']
|
28
|
+
gemspec.executables = ['ai', 'ttai']
|
29
29
|
gemspec.post_install_message = %q{
|
30
30
|
============================================================
|
31
31
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/bin/ai
CHANGED
@@ -16,11 +16,32 @@ begin
|
|
16
16
|
rescue CSD::Error::CSDError => e
|
17
17
|
# Here we catch CSD internal errors and exit with the propriate status code
|
18
18
|
# We output the error message only for status codes 50 and higher, because they are rather severe
|
19
|
-
|
19
|
+
if e.status_code >= 50
|
20
|
+
CSD.ui.error e.message
|
21
|
+
if e.status_code < 200
|
22
|
+
puts
|
23
|
+
puts " \e[31mPlease report bugs at:\e[0m \e[36mhttp://github.com/csd/csd/issues\e[0m"
|
24
|
+
puts
|
25
|
+
end
|
26
|
+
end
|
20
27
|
exit e.status_code
|
21
28
|
rescue Interrupt
|
22
29
|
# Lastly, close the AI gracefully on abnormal termination
|
23
30
|
CSD.ui.separator
|
24
31
|
CSD.ui.info "Quitting the AI...".red
|
25
32
|
exit 1
|
33
|
+
rescue ScriptError => e
|
34
|
+
puts "\e[31m\e[5mINTERNAL SCRIPT ERROR: \e[0m\e[31m#{e}\e[0m"
|
35
|
+
puts
|
36
|
+
puts e.backtrace.join("\n")
|
37
|
+
puts
|
38
|
+
puts " \e[31m\e[1mPlease report errors at:\e[0m \e[36mhttp://github.com/csd/csd/issues\e[0m"
|
39
|
+
puts
|
40
|
+
rescue StandardError => e
|
41
|
+
puts "\e[31m\e[5mINTERNAL ERROR: \e[0m\e[31m#{e}\e[0m"
|
42
|
+
puts
|
43
|
+
puts e.backtrace.join("\n")
|
44
|
+
puts
|
45
|
+
puts " \e[31m\e[1mPlease report errors at:\e[0m \e[36mhttp://github.com/csd/csd/issues\e[0m"
|
46
|
+
puts
|
26
47
|
end
|
data/bin/ttai
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# NOTE: If you would like to execute this file as a developer
|
4
|
+
# but not install the CSD gem, you can use this command:
|
5
|
+
# ruby -I path/to/csd/lib path/to/csd/bin/ai
|
6
|
+
|
7
|
+
# First, let's load the RubyGems framework and the CSD gem.
|
8
|
+
# Even though RubyGems is already loaded for Ruby >= 1.9,
|
9
|
+
# we want to go sure here and load it to provide robustness
|
10
|
+
require 'rubygems'
|
11
|
+
require 'csd'
|
12
|
+
|
13
|
+
begin
|
14
|
+
# Running the CSD library and telling it who started it
|
15
|
+
CSD.bootstrap :executable => 'ttai'
|
16
|
+
rescue CSD::Error::CSDError => e
|
17
|
+
# Here we catch CSD internal errors and exit with the propriate status code
|
18
|
+
# We output the error message only for status codes 50 and higher, because they are rather severe
|
19
|
+
if e.status_code >= 50
|
20
|
+
CSD.ui.error e.message
|
21
|
+
if e.status_code < 200
|
22
|
+
puts
|
23
|
+
puts " \e[31mPlease report bugs at:\e[0m \e[36mhttp://github.com/csd/csd/issues\e[0m"
|
24
|
+
puts
|
25
|
+
end
|
26
|
+
end
|
27
|
+
exit e.status_code
|
28
|
+
rescue Interrupt
|
29
|
+
# Lastly, close the AI gracefully on abnormal termination
|
30
|
+
CSD.ui.separator
|
31
|
+
CSD.ui.info "Quitting the AI...".red
|
32
|
+
exit 1
|
33
|
+
rescue ScriptError => e
|
34
|
+
puts "\e[31m\e[5mINTERNAL SCRIPT ERROR: \e[0m\e[31m#{e}\e[0m"
|
35
|
+
puts
|
36
|
+
puts e.backtrace.join("\n")
|
37
|
+
puts
|
38
|
+
puts " \e[31m\e[1mPlease report errors at:\e[0m \e[36mhttp://github.com/csd/csd/issues\e[0m"
|
39
|
+
puts
|
40
|
+
rescue StandardError => e
|
41
|
+
puts "\e[31m\e[5mINTERNAL ERROR: \e[0m\e[31m#{e}\e[0m"
|
42
|
+
puts
|
43
|
+
puts e.backtrace.join("\n")
|
44
|
+
puts
|
45
|
+
puts " \e[31m\e[1mPlease report errors at:\e[0m \e[36mhttp://github.com/csd/csd/issues\e[0m"
|
46
|
+
puts
|
47
|
+
end
|
data/csd.gemspec
CHANGED
@@ -5,15 +5,14 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{csd}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Technology Transfer Alliance Team"]
|
12
|
-
s.date = %q{2010-08-
|
13
|
-
s.default_executable = %q{ai}
|
12
|
+
s.date = %q{2010-08-25}
|
14
13
|
s.description = %q{CSD stands for Communication Systems Design and is a project of the Telecommunication Systems Laboratory (TSLab) of the Royal Institute of Technology in Stockholm, Sweden. Within CSD many software tools are used to build up various networks and services. This gem is supposed to automate processes to handle the compilation and installation of these software tools. Technology Transfer Alliance (TTA) is the project team, which maintains this code.}
|
15
14
|
s.email = %q{mtoday11@gmail.com}
|
16
|
-
s.executables = ["ai"]
|
15
|
+
s.executables = ["ai", "ttai"]
|
17
16
|
s.extra_rdoc_files = [
|
18
17
|
"README.rdoc"
|
19
18
|
]
|
@@ -25,6 +24,7 @@ Gem::Specification.new do |s|
|
|
25
24
|
"Rakefile",
|
26
25
|
"VERSION",
|
27
26
|
"bin/ai",
|
27
|
+
"bin/ttai",
|
28
28
|
"csd.gemspec",
|
29
29
|
"lib/csd.rb",
|
30
30
|
"lib/csd/application.rb",
|
@@ -34,6 +34,14 @@ Gem::Specification.new do |s|
|
|
34
34
|
"lib/csd/application/decklink/options/install.rb",
|
35
35
|
"lib/csd/application/default.rb",
|
36
36
|
"lib/csd/application/default/base.rb",
|
37
|
+
"lib/csd/application/i2conf.rb",
|
38
|
+
"lib/csd/application/i2conf/about.yml",
|
39
|
+
"lib/csd/application/i2conf/base.rb",
|
40
|
+
"lib/csd/application/i2conf/config_example.rb",
|
41
|
+
"lib/csd/application/i2conf/options/common.rb",
|
42
|
+
"lib/csd/application/i2conf/options/common_defaults.rb",
|
43
|
+
"lib/csd/application/i2conf/options/install.rb",
|
44
|
+
"lib/csd/application/i2conf/options/install_defaults.rb",
|
37
45
|
"lib/csd/application/minisip.rb",
|
38
46
|
"lib/csd/application/minisip/about.yml",
|
39
47
|
"lib/csd/application/minisip/base.rb",
|
@@ -42,13 +50,14 @@ Gem::Specification.new do |s|
|
|
42
50
|
"lib/csd/application/minisip/component/ffmpeg.rb",
|
43
51
|
"lib/csd/application/minisip/component/gnome.rb",
|
44
52
|
"lib/csd/application/minisip/component/hdviper.rb",
|
53
|
+
"lib/csd/application/minisip/component/network.rb",
|
45
54
|
"lib/csd/application/minisip/component/plugins.rb",
|
46
55
|
"lib/csd/application/minisip/component/x264.rb",
|
47
56
|
"lib/csd/application/minisip/error.rb",
|
48
57
|
"lib/csd/application/minisip/options/common.rb",
|
49
58
|
"lib/csd/application/minisip/options/common_defaults.rb",
|
50
|
-
"lib/csd/application/minisip/options/
|
51
|
-
"lib/csd/application/minisip/options/
|
59
|
+
"lib/csd/application/minisip/options/install.rb",
|
60
|
+
"lib/csd/application/minisip/options/install_defaults.rb",
|
52
61
|
"lib/csd/application/minisip/options/package.rb",
|
53
62
|
"lib/csd/application/minisip/options/package_defaults.rb",
|
54
63
|
"lib/csd/application/minisip/phonebook_example.rb",
|
data/lib/csd.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#-- encoding: UTF-8
|
2
|
+
require 'net/http'
|
2
3
|
|
3
4
|
# Loading all files in the subdirectory `csd´
|
4
5
|
Dir[File.join(File.dirname(__FILE__), 'csd', '*.rb')].sort.each { |path| require "csd/#{File.basename(path, '.rb')}" }
|
@@ -17,26 +18,62 @@ module CSD
|
|
17
18
|
def bootstrap(options={})
|
18
19
|
@executable = options[:executable]
|
19
20
|
Options.parse!
|
21
|
+
respond_to_internal_ai_options
|
20
22
|
respond_to_incomplete_arguments
|
21
|
-
UI.debug "#{self}.bootstrap initializes the task #{Options.action.enquote} of the application #{Applications.current.name.to_s.enquote} now"
|
22
|
-
Applications.current.instance.send("#{Options.action}".to_sym)
|
23
|
+
UI.debug "#{self}.bootstrap initializes the task #{Options.action.to_s.enquote if Options.action} of the application #{Applications.current.name.to_s.enquote if Applications.current} now"
|
24
|
+
Applications.current.instance.send("#{Options.action}".to_sym) if Applications.current
|
23
25
|
end
|
24
26
|
|
25
27
|
private
|
26
|
-
|
28
|
+
|
29
|
+
def respond_to_internal_ai_options
|
30
|
+
if !Applications.current and ARGV.include?('update')
|
31
|
+
update_ai_using_rubygems
|
32
|
+
elsif !Applications.current and ARGV.include?('edge')
|
33
|
+
update_ai_to_cutting_edge
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Updating the AI
|
38
|
+
#
|
39
|
+
def update_ai_using_rubygems
|
40
|
+
UI.info "Updating the AI to the newest version".green.bold
|
41
|
+
Cmd.run "sudo gem update csd --no-ri --no-rdoc", :announce_pwd => false, :verbose => true
|
42
|
+
exit!
|
43
|
+
end
|
44
|
+
|
45
|
+
# This method is used to conveniently update the AI without officially publishing it on RubyGems.
|
46
|
+
# This can be handy when testing many things on many machines at the same time :)
|
47
|
+
#
|
48
|
+
def update_ai_to_cutting_edge
|
49
|
+
UI.info "Updating the AI to the cutting-edge experimental version".green.bold
|
50
|
+
# Create a temporary working directory
|
51
|
+
Path.edge_tmp = Dir.mktmpdir
|
52
|
+
Path.edge_file = File.join(Path.edge_tmp, 'edge.gem')
|
53
|
+
# Retrieve list of possible locations for edge versions
|
54
|
+
# Note that you can just modify that list to add your own locations
|
55
|
+
# You can modify the list at http://github.com/csd/csd/downloads
|
56
|
+
# Note that the Amazon G3 cache used by Github takes about 12 hours to refresh the file, though!
|
57
|
+
for location in Net::HTTP.get_response(URI.parse('http://cloud.github.com/downloads/csd/csd/edge.txt')).body.split.each do
|
58
|
+
# See if there is a downloadable edge version at this location. If not, move on to the next location
|
59
|
+
next unless Cmd.download(location, Path.edge_file).success?
|
60
|
+
# If the download was successful here, let's update the AI from that downloaded gem-file and exit
|
61
|
+
updated = Cmd.run("sudo gem install #{Path.edge_file} --no-ri --no-rdoc", :announce_pwd => false, :verbose => true).success?
|
62
|
+
break
|
63
|
+
end
|
64
|
+
UI.info "Currently there is no edge version published.".green.bold unless updated
|
65
|
+
# Cleaning up the temporary directory
|
66
|
+
FileUtils.rm_r Path.edge_tmp
|
67
|
+
exit!
|
68
|
+
end
|
69
|
+
|
27
70
|
# This method check the arguments the user has provided and terminates the AI with
|
28
71
|
# some helpful message if the arguments are invalid.
|
29
72
|
#
|
30
73
|
def respond_to_incomplete_arguments
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
Cmd.run "sudo gem update csd --no-ri --no-rdoc", :announce_pwd => false, :verbose => true
|
35
|
-
exit # The only smooth status code 0 exit in this whole application :)
|
36
|
-
else
|
37
|
-
choose_application unless Applications.current
|
38
|
-
choose_action unless Options.valid_action?
|
39
|
-
end
|
74
|
+
choose_application unless Applications.current
|
75
|
+
choose_action unless Options.valid_action?
|
76
|
+
choose_scope if Options.scope and not Options.valid_scope?
|
40
77
|
end
|
41
78
|
|
42
79
|
# This methods lists all available applications
|
@@ -53,7 +90,6 @@ module CSD
|
|
53
90
|
end
|
54
91
|
UI.separator
|
55
92
|
UI.info ' For more information type: '.green.bold + "#{executable} [APPLICATION NAME]".cyan.bold + " Example: #{executable} minisip".dark
|
56
|
-
#UI.info ' For example: '.green.bold + "#{executable} minisip".cyan.bold
|
57
93
|
UI.separator
|
58
94
|
UI.warn "You did not specify a valid application name."
|
59
95
|
raise Error::Argument::NoApplication
|
@@ -65,7 +101,7 @@ module CSD
|
|
65
101
|
UI.separator
|
66
102
|
UI.info " Automated Installer assistance for #{Applications.current.human}".green.bold
|
67
103
|
UI.separator
|
68
|
-
UI.info " The AI can assist you with the following tasks regarding #{Applications.current.human}:
|
104
|
+
UI.info " The AI can assist you with the following tasks regarding #{Applications.current.human}:"
|
69
105
|
OptionParser.new do |opts|
|
70
106
|
opts.banner = ''
|
71
107
|
actions = Applications.current.actions['public']
|
@@ -74,12 +110,35 @@ module CSD
|
|
74
110
|
UI.info opts.help
|
75
111
|
end
|
76
112
|
UI.separator
|
77
|
-
|
78
|
-
UI.info '
|
113
|
+
example_action = Options.actions_names.empty? ? 'install' : Options.actions_names.first
|
114
|
+
UI.info ' To execute a task: '.green.bold + "#{executable} [TASK] #{Applications.current.name}".cyan.bold + " Example: #{executable} #{example_action} #{Applications.current.name}".dark
|
115
|
+
UI.info ' For more details: '.green.bold + "#{executable} help [TASK] #{Applications.current.name}".cyan.bold + " Example: #{executable} help #{example_action} #{Applications.current.name}".dark
|
79
116
|
UI.separator
|
80
117
|
UI.warn "You did not specify a valid task name."
|
81
118
|
raise Error::Argument::NoAction
|
82
119
|
end
|
120
|
+
|
121
|
+
# This methods lists all available scopes for a specific application and action
|
122
|
+
#
|
123
|
+
def choose_scope
|
124
|
+
UI.separator
|
125
|
+
UI.info " Automated Installer assistance to #{Options.action} #{Applications.current.human}".green.bold
|
126
|
+
UI.separator
|
127
|
+
UI.info " The AI can #{Options.action} the following #{Applications.current.human} components:"
|
128
|
+
OptionParser.new do |opts|
|
129
|
+
opts.banner = ''
|
130
|
+
scopes = Applications.current.scopes(Options.action)
|
131
|
+
scopes.flatten.each { |scope| opts.list_item(scope.keys.first, scope.values.first) }
|
132
|
+
UI.info opts.help
|
133
|
+
end
|
134
|
+
UI.separator
|
135
|
+
example_scope = Options.scopes_names.empty? ? 'myscope' : Options.scopes_names.first
|
136
|
+
UI.info ' To choose all components: '.green.bold + "#{executable} #{Options.action} #{Applications.current.name}".cyan.bold + " Example: #{executable} #{Options.action} #{Applications.current.name}".dark
|
137
|
+
UI.info ' To choose one component: '.green.bold + "#{executable} #{Options.action} #{Applications.current.name} [COMPONENT]".cyan.bold + " Example: #{executable} #{Options.action} #{Applications.current.name} #{example_scope}".dark
|
138
|
+
UI.separator
|
139
|
+
UI.warn "You did not specify a valid scope."
|
140
|
+
raise Error::Argument::NoAction
|
141
|
+
end
|
83
142
|
|
84
143
|
end
|
85
144
|
end
|
@@ -72,13 +72,13 @@ module CSD
|
|
72
72
|
file = Dir[File.join(Path.packages, "Deck*#{archflag}*.deb")]
|
73
73
|
UI.debug "#{self.class} identified these applicable packages: #{file.join(', ')}"
|
74
74
|
UI.info "Installing Debian packages".green.bold
|
75
|
-
Cmd.run "sudo apt-get install #{DEBIAN_DEPENDENCIES.join(' ')} --yes", :announce_pwd => false
|
75
|
+
Cmd.run "sudo apt-get install #{DEBIAN_DEPENDENCIES.join(' ')} --yes --force-yes", :announce_pwd => false
|
76
76
|
Cmd.run "sudo dpkg -i #{file.first || '[DRIVER FILE FOR THIS ARCHITECTURE]'}", :announce_pwd => false
|
77
77
|
end
|
78
78
|
|
79
79
|
def add_boot_loader
|
80
80
|
content = Path.kernel_module.file? ? File.read(Path.kernel_module) : ''
|
81
|
-
if content !~ /\nblackmagic/m
|
81
|
+
if content !~ /\nblackmagic/m or Options.reveal
|
82
82
|
UI.info "Adding Blackmagic drivers to the boot loader".green.bold
|
83
83
|
Cmd.touch_and_replace_content Path.new_kernel_module, "#{content}\nblackmagic"
|
84
84
|
Cmd.run "sudo cp #{Path.new_kernel_module} #{Path.kernel_module}", :announce_pwd => false
|
@@ -35,8 +35,7 @@ module CSD
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def scopes(action)
|
38
|
-
|
39
|
-
[]
|
38
|
+
about.scopes.key?(action) ? about.scopes[action] : []
|
40
39
|
end
|
41
40
|
|
42
41
|
# This method will look for application and task specific optionsfiles of the current application module.
|
@@ -45,7 +44,7 @@ module CSD
|
|
45
44
|
#
|
46
45
|
def options(action='')
|
47
46
|
result = []
|
48
|
-
["
|
47
|
+
["#{action}.rb", "common.rb"].each do |filename|
|
49
48
|
file = File.join(Path.applications, name, 'options', filename)
|
50
49
|
result << File.read(file) if File.file?(file)
|
51
50
|
end
|
@@ -37,7 +37,10 @@ module CSD
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def create_working_directory
|
40
|
-
|
40
|
+
UI.debug "The working directory is demanded to be #{Path.work}"
|
41
|
+
if Path.work.directory?
|
42
|
+
UI.debug "The working directory already exists and will not be created"
|
43
|
+
else
|
41
44
|
UI.info "Creating working directory".green.bold
|
42
45
|
Cmd.mkdir Path.work
|
43
46
|
end
|
@@ -46,7 +49,7 @@ module CSD
|
|
46
49
|
def cleanup_working_directory
|
47
50
|
if !Options.work_dir and Options.temp and !Options.this_user and Path.work.directory?
|
48
51
|
UI.info "Removing working directory".green.bold
|
49
|
-
UI.debug "
|
52
|
+
UI.debug "MILESTONE_deleting_work_dir"
|
50
53
|
# TODO: Make this Windows working
|
51
54
|
Cmd.run "sudo rm -Rf #{Path.work}", :announce_pwd => false
|
52
55
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: UTF-8 -*-
|
2
|
+
require 'csd/application/default/base'
|
3
|
+
require 'csd/application/i2conf/base'
|
4
|
+
|
5
|
+
module CSD
|
6
|
+
module Application
|
7
|
+
# This is the Application Module for i2conf, a sip video conference MCU.
|
8
|
+
#
|
9
|
+
module I2conf
|
10
|
+
class << self
|
11
|
+
|
12
|
+
include CSD::Application::Default
|
13
|
+
|
14
|
+
# This method will check which system we're on and initialize the correct sub-module
|
15
|
+
#
|
16
|
+
def instance
|
17
|
+
if Gem::Platform.local.ubuntu?
|
18
|
+
UI.debug "#{self}.instance initializes the i2conf Base class now"
|
19
|
+
Base.new
|
20
|
+
else
|
21
|
+
raise 'Sorry, currently only Ubuntu is supported.'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
# -*- encoding: UTF-8 -*-
|
2
|
+
require 'csd/application/default/base'
|
3
|
+
require 'csd/application/minisip/unix/linux/debian'
|
4
|
+
require 'csd/application/i2conf/config_example'
|
5
|
+
|
6
|
+
module CSD
|
7
|
+
module Application
|
8
|
+
module I2conf
|
9
|
+
class Base < CSD::Application::Base
|
10
|
+
|
11
|
+
include ::CSD::Application::Minisip::Component
|
12
|
+
|
13
|
+
DESKTOP_ENTRY = %{
|
14
|
+
[Desktop Entry]
|
15
|
+
Encoding=UTF-8
|
16
|
+
Name=i2conf MCU
|
17
|
+
GenericName=SIP Multipoint Control Unit (Reflector)
|
18
|
+
Comment=Provide a multi-party video conference room
|
19
|
+
Exec=PLACEHOLDER
|
20
|
+
Icon=i2conf_gnome
|
21
|
+
Terminal=true
|
22
|
+
Type=Application
|
23
|
+
StartupNotify=true
|
24
|
+
Categories=Application;Internet;Network;Chat;AudioVideo}
|
25
|
+
|
26
|
+
GNOME_ICON_URL = 'http://github.com/downloads/csd/i2conf/i2conf_gnome.png'
|
27
|
+
|
28
|
+
# A list of apt-get packages that are required to install i2conf.
|
29
|
+
#
|
30
|
+
DEBIAN_DEPENDENCIES = %w{ libboost-dev libboost-thread-dev liblog4cxx* }
|
31
|
+
|
32
|
+
def install
|
33
|
+
@minisip = ::CSD::Application::Minisip::Debian.new
|
34
|
+
define_relative_paths
|
35
|
+
UI.separator
|
36
|
+
UI.info "This operation will download and install the i2conf SIP video conferencing MCU.".green.bold
|
37
|
+
UI.separator
|
38
|
+
introduction
|
39
|
+
install!
|
40
|
+
end
|
41
|
+
|
42
|
+
def install!
|
43
|
+
create_working_directory
|
44
|
+
compile_minisip
|
45
|
+
aptitude
|
46
|
+
checkout_strmanager
|
47
|
+
copy_libtool
|
48
|
+
fix_str_manager
|
49
|
+
compile_str_manager
|
50
|
+
checkout_i2conf
|
51
|
+
fix_i2conf
|
52
|
+
fix_i2conf_aclocal
|
53
|
+
compile_i2conf
|
54
|
+
create_desktop_entry
|
55
|
+
configure_i2conf
|
56
|
+
send_notification
|
57
|
+
congratulations
|
58
|
+
end
|
59
|
+
|
60
|
+
def compile_minisip
|
61
|
+
return unless Options.minisip
|
62
|
+
@minisip.aptitude
|
63
|
+
Options.only = %w{ libmutil libmnetutil libmcrypto libmikey libmsip libmstun libminisip }
|
64
|
+
Options.blank_minisip_configuration = true
|
65
|
+
Options.bootstrap = true
|
66
|
+
Options.configure = true
|
67
|
+
Options.make = true
|
68
|
+
Options.make_install = true
|
69
|
+
Core.checkout
|
70
|
+
Core.modify_dirlist
|
71
|
+
Core.compile_libraries
|
72
|
+
Core.link_libraries
|
73
|
+
end
|
74
|
+
|
75
|
+
def aptitude
|
76
|
+
return unless Options.apt_get
|
77
|
+
UI.info "Installing Debian dependencies for i2conf".green.bold
|
78
|
+
Cmd.run 'sudo apt-get update', :announce_pwd => false
|
79
|
+
Cmd.run "sudo apt-get install #{DEBIAN_DEPENDENCIES.sort.join(' ')} --yes --fix-missing", :announce_pwd => false
|
80
|
+
end
|
81
|
+
|
82
|
+
def checkout_strmanager
|
83
|
+
Cmd.git_clone('strManager library', 'git://github.com/csd/strManager.git', Path.str_manager)
|
84
|
+
end
|
85
|
+
|
86
|
+
def copy_libtool
|
87
|
+
UI.info 'Copying libtool dependencies'.green.bold
|
88
|
+
Cmd.cd Path.str_manager, :internal => true
|
89
|
+
Cmd.run 'cp /usr/share/libtool/config/config.sub .'
|
90
|
+
Cmd.run 'cp /usr/share/libtool/config/config.guess .'
|
91
|
+
Cmd.run 'cp /usr/share/libtool/config/ltmain.sh .'
|
92
|
+
end
|
93
|
+
|
94
|
+
def fix_str_manager
|
95
|
+
UI.info 'Fixing strManager'.green.bold
|
96
|
+
[Path.str_src_manager, Path.str_src_worker].each do |file|
|
97
|
+
if Options.reveal or !File.read(file).include?('#include <iostream>')
|
98
|
+
Cmd.replace file, '#include', "#include <iostream>\n#include", { :only_first_occurence => true }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def compile_str_manager
|
104
|
+
UI.info 'Compiling strManager'.green.bold
|
105
|
+
Cmd.cd Path.str_manager, :internal => true
|
106
|
+
Cmd.run './configure'
|
107
|
+
Cmd.run 'aclocal'
|
108
|
+
Cmd.run 'make'
|
109
|
+
Cmd.run 'sudo make install'
|
110
|
+
Cmd.run "sudo ldconfig /usr/local/lib/libstrmanager.so", :announce_pwd => false
|
111
|
+
end
|
112
|
+
|
113
|
+
def checkout_i2conf
|
114
|
+
Cmd.git_clone('i2conf repository', 'git://github.com/csd/i2conf.git', Path.i2conf)
|
115
|
+
end
|
116
|
+
|
117
|
+
def fix_i2conf
|
118
|
+
if Options.reveal or !File.read(Path.i2conf_bootstrap).include?('automake-1.11')
|
119
|
+
UI.info 'Fixing i2conf automake'.green.bold
|
120
|
+
Cmd.replace Path.i2conf_bootstrap, 'elif automake-1.10', %{elif automake-1.11 --version >/dev/null 2>&1; then\n amvers="-1.11"\nelif automake-1.10}, { :only_first_occurence => true }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def fix_i2conf_aclocal
|
125
|
+
if Options.reveal or File.read(Path.i2conf_bootstrap).include?('-I m4')
|
126
|
+
UI.info 'Fixing i2conf aclocal'.green.bold
|
127
|
+
Cmd.replace Path.i2conf_bootstrap, '-I m4 ', ''
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def compile_i2conf
|
132
|
+
UI.info 'Compiling i2conf'.green.bold
|
133
|
+
Cmd.cd Path.i2conf, :internal => true
|
134
|
+
Cmd.run './bootstrap'
|
135
|
+
Cmd.run './configure'
|
136
|
+
Cmd.run 'aclocal'
|
137
|
+
Cmd.run 'make'
|
138
|
+
Cmd.run 'sudo make install'
|
139
|
+
end
|
140
|
+
|
141
|
+
def create_desktop_entry
|
142
|
+
UI.info "Installing Gnome menu item".green.bold
|
143
|
+
if Cmd.download(GNOME_ICON_URL, Path.i2conf_gnome_png).success?
|
144
|
+
Cmd.run("sudo cp #{Path.i2conf_gnome_png} #{Path.i2conf_gnome_pixmap}", :announce_pwd => false)
|
145
|
+
Cmd.touch_and_replace_content Path.i2conf_new_desktop_entry, DESKTOP_ENTRY.sub('PLACEHOLDER', "i2conf -f #{Path.i2conf_example_conf}"), :internal => true
|
146
|
+
Cmd.run "sudo mv #{Path.i2conf_new_desktop_entry} #{Path.i2conf_desktop_entry}", :announce_pwd => false
|
147
|
+
Gnome.update_gnome_menu_cache
|
148
|
+
else
|
149
|
+
UI.warn "The menu item could not be created, because the image file could not be downloaded from #{GNOME_ICON_URL}.".green.bold
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def configure_i2conf
|
154
|
+
if Path.i2conf_example_conf.file?
|
155
|
+
UI.warn "Creating no example configuration file, because it already exists: #{Path.i2conf_example_conf}. "
|
156
|
+
else
|
157
|
+
UI.info "Creating example i2conf configuration file".green.bold
|
158
|
+
Cmd.touch_and_replace_content Path.i2conf_example_conf, ::CSD::Application::I2conf::CONFIG_EXAMPLE
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def send_notification
|
163
|
+
Cmd.run %{notify-send --icon=i2conf_gnome "I2conf installation complete" "You are now ready to use your SIP MCU." }, :internal => true, :die_on_failure => false
|
164
|
+
end
|
165
|
+
|
166
|
+
def congratulations
|
167
|
+
cleanup_working_directory if Options.temp
|
168
|
+
UI.separator
|
169
|
+
UI.info " i2conf installation complete.".green.bold
|
170
|
+
UI.separator
|
171
|
+
UI.info " 1. Change the password in the example configuration file:".yellow
|
172
|
+
UI.info " #{Path.i2conf_example_conf}".cyan
|
173
|
+
UI.separator
|
174
|
+
UI.info " 2. Start the MCU".yellow
|
175
|
+
UI.info " Application menu -> Internet".cyan
|
176
|
+
UI.info " or"
|
177
|
+
UI.info " i2conf -f #{Path.i2conf_example_conf}".cyan
|
178
|
+
UI.separator
|
179
|
+
end
|
180
|
+
|
181
|
+
def introduction
|
182
|
+
UI.info " Working directory: ".green.bold + Path.work.to_s.yellow
|
183
|
+
if Options.debug
|
184
|
+
UI.info " Your Platform: ".green + Gem::Platform.local.humanize.to_s.yellow
|
185
|
+
UI.info(" Application module: ".green + self.class.name.to_s.yellow)
|
186
|
+
end
|
187
|
+
UI.separator
|
188
|
+
if Options.help
|
189
|
+
UI.info Options.helptext
|
190
|
+
# Cleanup in case the working directory was temporary and is empty
|
191
|
+
Path.work.rmdir if Options.temp and Path.work.directory? and Path.work.children.empty?
|
192
|
+
raise CSD::Error::Argument::HelpWasRequested
|
193
|
+
else
|
194
|
+
raise Interrupt unless Options.yes or Options.reveal or UI.continue?
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def define_relative_paths
|
199
|
+
UI.debug "#{self.class}#define_relative_paths defines relative i2conf paths now"
|
200
|
+
Path.str_manager = Pathname.new(File.join(Path.work, 'libstrmanager'))
|
201
|
+
Path.str_src_manager = Pathname.new(File.join(Path.str_manager, 'src', 'Manager.cpp'))
|
202
|
+
Path.str_src_worker = Pathname.new(File.join(Path.str_manager, 'src', 'workers', 'StatsWorker.cpp'))
|
203
|
+
Path.i2conf = Pathname.new(File.join(Path.work, 'i2conf'))
|
204
|
+
Path.i2conf_bootstrap = Pathname.new(File.join(Path.i2conf, 'bootstrap'))
|
205
|
+
Path.i2conf_example_conf = Pathname.new(File.join(ENV['HOME'], 'i2conf.example.xml'))
|
206
|
+
Path.i2conf_gnome_png = Pathname.new(File.join(Path.work, 'i2conf_gnome.png'))
|
207
|
+
Path.i2conf_gnome_pixmap = Pathname.new(File.join('/', 'usr', 'share', 'pixmaps', 'i2conf_gnome.png'))
|
208
|
+
Path.i2conf_desktop_entry = Pathname.new(File.join('/', 'usr', 'share', 'applications', 'i2conf.desktop'))
|
209
|
+
Path.i2conf_new_desktop_entry = Pathname.new(File.join(Path.work, 'i2conf.desktop'))
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|