Merge branch 'master' into 2221-complete-docker
[arvados.git] / docker / build.rb
1 #! /usr/bin/env ruby
2
3 require 'tempfile'
4 require 'yaml'
5
6 def sudo(*cmd)
7   # user can pass a single list in as an argument
8   # to allow usage like: sudo %w(apt-get install foo)
9   warn "You may need to enter your password here."
10   if cmd.length == 1 and cmd[0].class == Array
11     cmd = cmd[0]
12   end
13   system '/usr/bin/sudo', *cmd
14 end
15
16 def is_valid_email? str
17   str.match /^\S+@\S+\.\S+$/
18 end
19
20 def generate_api_hostname
21   rand(2**256).to_s(36)[0...5]
22 end
23
24 # ip_forwarding_enabled?
25 #   Returns 'true' if IP forwarding is enabled in the kernel
26 #
27 def ip_forwarding_enabled?
28   %x(/sbin/sysctl -n net.ipv4.ip_forward) == "1\n"
29 end
30
31 def debootstrap_ok?
32   return system '/usr/sbin/debootstrap --version > /dev/null 2>&1'
33 end
34
35 def docker_ok?
36   return system 'docker images > /dev/null 2>&1'
37 end
38
39 # find_or_create_ssh_key arvados_name
40 #   Return the SSH public key appropriate for this Arvados instance,
41 #   generating one if necessary.
42 #
43 def find_or_create_ssh_key arvados_name
44   ssh_key_file = "#{ENV['HOME']}/.ssh/arvados_#{arvados_name}_id_rsa"
45   unless File.exists? ssh_key_file
46     system 'ssh-keygen',
47            '-f', ssh_key_file,
48            '-C', "arvados@#{arvados_name}",
49            '-P', ''
50   end
51
52   return "#{ssh_key_file}.pub"
53 end
54
55 if not ip_forwarding_enabled?
56   warn "NOTE: IP forwarding must be enabled in the kernel."
57   warn "Turning IP forwarding on now."
58   sudo %w(/sbin/sysctl net.ipv4.ip_forward=1)
59 end
60
61 # Check that:
62 #   * Docker is installed and can be found in the user's path
63 #   * Docker can be run as a non-root user
64 #      - TODO: put the user is in the docker group if necessary
65 #      - TODO: mount cgroup automatically
66 #      - TODO: start the docker service if not started
67
68 docker_path = %x(which docker).chomp
69 if docker_path.empty?
70   warn "Docker not found."
71   warn ""
72   warn "Please make sure that Docker has been installed and"
73   warn "can be found in your PATH."
74   warn ""
75   warn "Installation instructions for a variety of platforms can be found at"
76   warn "http://docs.docker.io/en/latest/installation/"
77   exit
78 elsif not docker_ok?
79   warn "WARNING: docker could not be run."
80   warn "Please make sure that:"
81   warn "  * You have permission to read and write /var/run/docker.sock"
82   warn "  * a 'cgroup' volume is mounted on your machine"
83   warn "  * the docker daemon is running"
84   exit
85 end
86
87 # Check that debootstrap is installed.
88 if not debootstrap_ok?
89   warn "Installing debootstrap."
90   sudo '/usr/bin/apt-get', 'install', 'debootstrap'
91 end
92
93 # Generate a config.yml if it does not exist or is empty
94 if not File.size? 'config.yml'
95   print "Generating config.yml.\n"
96   print "Arvados needs to know the email address of the administrative user,\n"
97   print "so that when that user logs in they are automatically made an admin.\n"
98   print "This should be the email address you use to log in to Google.\n"
99   print "\n"
100   admin_email_address = ""
101   until is_valid_email? admin_email_address
102     print "Enter your Google ID email address here: "
103     admin_email_address = gets.strip
104     if not is_valid_email? admin_email_address
105       print "That doesn't look like a valid email address. Please try again.\n"
106     end
107   end
108
109   File.open 'config.yml', 'w' do |config_out|
110     config = YAML.load_file 'config.yml.example'
111     config['API_AUTO_ADMIN_USER'] = admin_email_address
112     config['API_HOSTNAME'] = generate_api_hostname
113     config['PUBLIC_KEY_PATH'] = find_or_create_ssh_key(config['API_HOSTNAME'])
114     config.each_key do |var|
115       if var.end_with?('_PW') or var.end_with?('_SECRET')
116         config[var] = rand(2**256).to_s(36)
117       end
118       config_out.write "#{var}: #{config[var]}\n"
119     end
120   end
121 end
122
123 # If all prerequisites are met, go ahead and build.
124 if ip_forwarding_enabled? and
125     docker_ok? and
126     debootstrap_ok? and
127     File.exists? 'config.yml'
128   warn "Building Arvados."
129   system '/usr/bin/make', *ARGV
130 end
131
132 # install_docker
133 #   Determine which Docker package is suitable for this Linux distro
134 #   and install, resolving any dependencies.
135 #   NOTE: not in use yet.
136
137 def install_docker
138   linux_distro = %x(lsb_release --id).split.last
139   linux_release = %x(lsb_release --release).split.last
140   linux_version = linux_distro + " " + linux_release
141   kernel_release = `uname -r`
142   
143   case linux_distro
144   when 'Ubuntu'
145     if not linux_release.match '^1[234]\.'
146       warn "Arvados requires at least Ubuntu 12.04 (Precise Pangolin)."
147       warn "Your system is Ubuntu #{linux_release}."
148       exit
149     end
150     if linux_release.match '^12' and kernel_release.start_with? '3.2'
151       # Ubuntu Precise ships with a 3.2 kernel and must be upgraded.
152       warn "Your kernel #{kernel_release} must be upgraded to run Docker."
153       warn "To do this:"
154       warn "  sudo apt-get update"
155       warn "  sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring"
156       warn "  sudo reboot"
157       exit
158     else
159       # install AUFS
160       sudo 'apt-get', 'update'
161       sudo 'apt-get', 'install', "linux-image-extra-#{kernel_release}"
162     end
163
164     # add Docker repository
165     sudo %w(/usr/bin/apt-key adv
166               --keyserver keyserver.ubuntu.com
167               --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9)
168     source_file = Tempfile.new('arv')
169     source_file.write("deb http://get.docker.io/ubuntu docker main\n")
170     source_file.close
171     sudo '/bin/mv', source_file.path, '/etc/apt/sources.list.d/docker.list'
172     sudo %w(/usr/bin/apt-get update)
173     sudo %w(/usr/bin/apt-get install lxc-docker)
174
175     # Set up for non-root access
176     sudo %w(/usr/sbin/groupadd docker)
177     sudo '/usr/bin/gpasswd', '-a', ENV['USER'], 'docker'
178     sudo %w(/usr/sbin/service docker restart)
179   when 'Debian'
180   else
181     warn "Must be running a Debian or Ubuntu release in order to run Docker."
182     exit
183   end
184 end
185