Making ubuntu-6.06.1-server-i386 the current template.
[mwamko.git] / install.rb
blob00a945f7edc123bc9a3cab46233db2e5f678a058
1 SCRIPT_PATH = File.dirname(File.expand_path(__FILE__))
3 require 'open3'
6 module Install
8   INSTALLED_DPKGS = `dpkg -l | awk '{print $2}'`.split("\n")
9 #  # NOTE: INSTALLED_DPKGS does not work quite as expected
12   def self.puts(data='')
13     data ||= ''
14     
15     if @log_file.nil?
16       postfix = ".#{Time.now.strftime("%Y%m%d_%H%M%S")}"
17       @log_file = File.new("#{SCRIPT_PATH}/log/install.log#{postfix}", 
18           File::CREAT|File::TRUNC|File::WRONLY)
19     end
20     
21     @log_file << data << "\n"
22     @log_file.flush
24     super data
25     
26     return nil
27   end
30   def Install.`(cmd) # ` emacs fix     
31     puts cmd       
33     i, o, e = Open3.popen3(cmd)
35     # Gather STDOUT first!
36     output = o.entries.join
38     puts e.entries.join
39     puts output
41     puts
43     return output
44   end
45   
46   WHOAMI = `whoami`.strip
47   if WHOAMI != 'root'
48     puts '
49   Permission Denied
52     exit
53   end
54   
55   last_step_in_bash = 9
56   
57   class NextStep
58     def initialize(initial_value)
59       @s ||= initial_value
60     end
61     def next!
62       @s += 1      
63       return "\n---> Step #@s"
64     end
65   end
67   print_step = NextStep.new(last_step_in_bash)
69   def Install.expected_src_compression(url)
70     if url =~ /^.*\/(.*)(\.tgz|\.tar\.gz|\.zip|\.tar\.bz2)$/
71       case $2 
72       when '.tar.gz'
73         return 'gzip'
74       when '.tgz'
75         return 'gzip'
76       when '.tar.bz2'
77         return 'bzip2'
78       else
79         raise "Unknown file extension for #{$&.inspect}"
80       end
81         
82     else
83       raise "Invalid: #@rubygems_src_url"
84     end
85   end
87   def Install.expected_src_dir(url)
88     if url =~ /^.*\/(.*)(\.tgz|\.tar\.gz|\.zip|\.tar\.bz2)$/
89       return "#@sources_dir/#{$1}"
90     else
91       raise "Invalid: #{url}"
92     end
93   end
95   def Install.download_open_source(url)
96     if File.exists?(File.expand_path(expected_src_dir(url)))
97       puts "Skipped!"
98     else
99       compression = expected_src_compression(url)
100       `wget -O- #{url} | tar -C #@sources_dir --#{compression} -xvf -`
101     end
102   end
104   def Install.apt_install(package)
105     ## PROBLEM: dpkg show as if the package is still there if
106     ## there it's marked as C (conflicting)
108     #if INSTALLED_PACKAGES.include?(package)
109     #  puts "Skipped!"
110     #else
111       `apt-get install #{package} --assume-yes --no-remove` 
112     #end      
113   end
115   def Install.check_mysql_password(pw)
116     i, o, e = Open3.popen3("mysqladmin --password=\"#{pw}\" -u root password \"#{pw}\"")
117     #Gather output
118     o.entries
120     return true if e.entries.join('').empty?
121     return false
123   end
125   def Install.set_mysql_password(new_pw)
126     #This will only set the password if the current root password is empty.
127     i, o, e = Open3.popen3("mysqladmin -u root password \"#{new_pw}\"")
128     #Gather output
129     o.entries
131     errs = e.entries.join("\n")
132     return true if errs.empty?
134     raise errs
135   end
137   def Install.get_config_mysql_password
138     File.open("#{SCRIPT_PATH}/config/database.yml").each do |line|
139       if line =~ /^[ ]*password:[ ]*([^\s]*)/
140         return $1 
141       end
142     end
143   end
145   
146   def Install.gem_install(package, arguments)
147     if INSTALLED_GEMS.include?(package)
148       puts 'Skipped!'
149     else
150       `gem install #{package} #{arguments} --include-dependencies --remote`
151     end
152   end
154   puts print_step.next!
155   # Installing emacs with ruby-mode and a spell-checker
156   # because otherwise some Mwamko developers will have a 
157   # had time maintaining this server without their 
158   # favorite editor
159   
160   apt_install('emacs21-nox')
161   apt_install('ruby1.8-elisp')
162   apt_install('ispell')
163   
165   puts print_step.next!
166   apt_install('mysql-client')
167   apt_install('mysql-server')
170   puts print_step.next!
172   @sources_dir = File.expand_path("#{SCRIPT_PATH}/../mwamko_dependencies")
173   `mkdir --parents #@sources_dir`
174   `chown -R --no-dereference --reference=#{SCRIPT_PATH}/.. #@sources_dir`
176   @rubygems_src_url = 
177     "http://rubyforge.org/frs/download.php/17190/rubygems-0.9.2.tgz"
179   @lighttpd_src_url =
180     "http://www.lighttpd.net/assets/2007/1/29/lighttpd-1.4.13.tar.gz"
182   @vzctl_src_url =
183     "http://download.openvz.org/utils/vzctl/3.0.16/src/vzctl-3.0.16.tar.bz2"
185   @vzquota_src_url =
186     "http://download.openvz.org/utils/vzquota/3.0.9/src/vzquota-3.0.9.tar.bz2"
188   puts print_step.next!
189   download_open_source(@rubygems_src_url)
192   puts print_step.next!
193   if File.exists?('/usr/bin/gem')
194     puts "Skipped!"
195   else
196     `cd #{expected_src_dir(@rubygems_src_url)}; ruby setup.rb`
197   end
200   puts print_step.next!
201   puts "Installing Lighttpd dependencies ..."
202   puts
204   apt_install('build-essential')
205   apt_install('openssl')
206   apt_install('libssl-dev')
207   apt_install('zlib1g-dev')
208   apt_install('libpcre3-dev')
209   apt_install('libpcre3')
210   # lighttpd 1.5.0 will require libglibmm-2.4-dev
211   
212   
213   # Universe package
214   apt_install('libfcgi-dev')
215   apt_install('libfcgi-ruby1.8')
217   puts print_step.next!
218   download_open_source(@lighttpd_src_url)
220   puts print_step.next!
221   if File.exists?('/usr/local/sbin/lighttpd')
222     puts "Skipped!"
223   else
224     lighttpd_config = 
225       "./configure --with-openssl --with-openssl-libs=/usr/lib"
226     cmd = "cd #{expected_src_dir(@lighttpd_src_url)}; #{lighttpd_config}"
227     cmd += "; make"
228     cmd += "; make install"
229     `#{cmd}`
230   end
232   puts print_step.next!
233   `mkdir --parents /var/www/html`
236   puts print_step.next!
237   puts "Coping Rails MySQL configuration file"
239   traditional_db_config_path = "#{SCRIPT_PATH}/config/database.yml"
240   db_config_template  = "#{SCRIPT_PATH}/config/database.template"
242   `mkdir /etc/mwamko`
243   
244   cmd = "cat #{SCRIPT_PATH}/config/available_ip_addresses.range.template > " +
245         "/etc/mwamko/available_ip_addresses.range.rb" 
246   `#{cmd}`
248   `cp #{SCRIPT_PATH}/config/dns.settings.template /etc/mwamko/dns.settings.rb`
249   `touch /etc/mwamko/allowed_emails.list`
252   unless File.exists? '/etc/mwamko/database.yml'
253     cmd = "cp #{db_config_template} /etc/mwamko/database.yml"
254     `#{cmd}`
255   end
257   `chmod -R a+Xr /etc/mwamko`
259   cmd = "unlink #{traditional_db_config_path}"
260   `#{cmd}`
262   cmd = "ln -s /etc/mwamko/database.yml #{traditional_db_config_path}"
263   `#{cmd}`
265   cmd = 
266     "chown --no-dereference --reference=#{SCRIPT_PATH}/.. " +
267     traditional_db_config_path
269   `#{cmd}`
271   puts print_step.next!
272   puts "Setting-up MySQL"
274   rails_config_file = traditional_db_config_path
276   if not check_mysql_password(get_config_mysql_password) and not get_config_mysql_password != ''
277     puts "Incorrect password in #{traditional_db_config_path}"
278     exit
279   end
281   if not check_mysql_password('')
282     if get_config_mysql_password == ''
283       puts "
284         MySQL has a password for root.
285         You must put this password in #{traditional_db_config_path}
286       "
287       exit
288     end
289   else
290     #The root password is blank
291     
292     require 'lib/password_gen'
293     new_password = PasswordGen.generate_pronounceable(16)
294        
295     puts 'setting mysql root password to ' + new_password
296     result = set_mysql_password(new_password)
297     
298     raise "failed to set mysql password" unless result
300     i, o, e = 
301       Open3.popen3("sed 's/\\(password:\\).*$/\\1 #{new_password}/'" +
302                    " < #{rails_config_file}")
304     # Gather STDOUT first!
305     db_config_temporary = 
306       "#{rails_config_file}.tmp.#{Time.now.to_i}"
308     f = File.open(db_config_temporary, 
309                   File::CREAT|File::TRUNC|File::WRONLY)
310     o.each do |line|
311       f << line
312     end
313     f.close
314     
315     errors = e.entries.join
316     raise "Got unexpected STDERR: #{errors}" if errors  != ''
318     `cat #{db_config_temporary} > #{rails_config_file}`
319     `rm #{db_config_temporary}`
322     ['mwamko_production', 'mwamko_test'].each do |db_name|
323       i, o, e = 
324         Open3.popen3(["mysqladmin create #{db_name}", 
325                       "-u root --password=#{new_password}"].join(' '))
326       # Gather STDOUT first!
327       o.entries
328     
329       errors = e.entries.join
330       unless errors.empty?
331         raise "Error when creating database: #{errors}"
332       end
333     end
335     new_password = ''
336   end
339   puts print_step.next!
340   puts "Installing the mysql rubygem dependencies..."
341   puts
342   apt_install('ruby1.8-dev')
343   apt_install('libmysqlclient15-dev')
346   INSTALLED_GEMS = 
347     `gem list | grep -v "^ " | awk '{print $1}'`.split("\n")
349   INSTALLED_GEMS.delete("")
350   INSTALLED_GEMS.delete_at(0)  
352   puts print_step.next!
353   puts "Installing Rails..."
354   puts
355   `wget --directory-prefix=#{@sources_dir} \
356    http://wiki.mwamko.cs.ucr.edu/download/rails-1.2.3-gems.tar.bz2`
357   `tar --directory #{@sources_dir} -jxf #{@sources_dir}/*tar.bz2`
358   `gem install #{@sources_dir}/rails-1.2.3-gems/*\.gem`
360   puts print_step.next!
361   puts "Installing the mysql rubygem..."
362   gem_install "mysql", "--version 2.7"
367   puts print_step.next!
368   `cd #{SCRIPT_PATH}; rake db:migrate RAILS_ENV=production`
371   puts print_step.next!
372   puts 'Installing dependencies for BackgroundRb...'
374   gem_install "daemons", ''
375   gem_install "slave", ''
376     
377   
378   puts print_step.next!
379   unless `uname -r` =~ /ovz/
380     puts "WARNING: You do not seem to be running under an OpenVZ kernel."
381     puts "         I was expecting to see 'ovz' in the kernel-release name."
382     puts "         Mwamko will not be able to operate without OpenVZ."
384     exit
385   else
386     puts "OpenVZ kernel detection ... PASSED"
387   end
390   puts print_step.next!
391   download_open_source(@vzctl_src_url)
393   puts print_step.next!
394   if File.exists?('/usr/local/sbin/vzctl')
395     puts "Skipped!"
396   else
397     config = 
398       "./configure"
399     `cd #{expected_src_dir(@vzctl_src_url)}; #{config}; make`
400     `make install -C #{expected_src_dir(@vzctl_src_url)}`
402     ['arpsend'].each do |n|
403     `ln -s /usr{/local,}/sbin/#{n}`
404     end
405   end
408   puts print_step.next!
409   download_open_source(@vzquota_src_url)
411   puts print_step.next!
412   if File.exists?('/usr/sbin/vzqouta')
413     puts "Skipped!"
414   else
415     src_path = expected_src_dir(@vzquota_src_url)
416     `make install -C #{src_path}`
418     ['vzquota', 'vzdqdump', 'vzdqload', 'vzdqcheck'].each do |n|
419       `ln -s /usr{,/local}/sbin/#{n}`
420     end
421   end
425   puts print_step.next!
426   puts "Setting-up the mwamko user"
428   puts print_step.next!
430   `userdel mwamko`
431   `groupdel mwmako`
432   
433   `groupadd mwamko`
434   `useradd --create-home --gid mwamko mwamko`
435   
438   # TODO: Stop it from leaving a whole bunch of new lines
439   puts "Removing all lines with %mwamko from /ect/sudoers"
440   `su -c "sed 's/.*%mwamko.*//' < /etc/sudoers > /etc/sudoers.mwamko.tmp"`
441   `cp /etc/sudoers.mwamko.tmp /etc/sudoers`
442   `rm /etc/sudoers.mwamko.tmp`
443   
444   puts "Granting some sudoers permissions to the mwamko group"
445   `su -c "echo  %mwamko ALL=\\(ALL\\)       NOPASSWD: /usr/local/sbin/lighttpd >> /etc/sudoers"`
447   `su -c "echo  %mwamko ALL=\\(ALL\\)       NOPASSWD: /usr/local/sbin/vzctl >> /etc/sudoers"` 
449   `su -c "echo  %mwamko ALL=\\(ALL\\)       NOPASSWD: /usr/local/sbin/vzlist >> /etc/sudoers"`
451   `su -c "echo  %mwamko ALL=\\(ALL\\)       NOPASSWD: /bin/mv >> /etc/sudoers"`
452   `su -c "echo  %mwamko ALL=\\(ALL\\)       NOPASSWD: /bin/cat >> /etc/sudoers"`
456   puts print_step.next!
457   puts "NOTE: If the system is restarted then this will be lost."
458   puts "This should be in a system startup script"
460   `modprobe vzdquota`
461   `modprobe vzmon`
462   `modprobe vzdev`
463   `modprobe vznetdev`
464   `modprobe vzethdev`
465   `modprobe vzrst`
467   `ip link set venet0 up`
468   `ip addr add 0.0.0.0/0 dev venet0`
469   `sysctl -w net.ipv4.conf.venet0.send_redirects=0`
470   
472   puts print_step.next!
473   puts "Cleaning up any previously started Mwamko services"
475   `killall lighttpd`  
477   brb_pid = `ps -A -o pid,command | awk '/backgroundrb$/ {print $1}'`
478   brb_pid.each do |pid|
479     `kill #{brb_pid.to_i}`
480   end
483   puts print_step.next!
484   `./lib/tasks/install_openvz/sysctl_setup`
486   puts print_step.next!
487   `cp -pdr ../mwamko ~mwamko/`
488   `chown -R mwamko:mwamko ~mwamko/mwamko`
489   `su mwamko -c "~/mwamko/script/server start_after_install production"`