8 if not ip_forwarding_enabled?
9 warn "NOTE: IP forwarding must be enabled in the kernel."
10 warn "Turning IP forwarding on now."
11 sudo %w(/sbin/sysctl net.ipv4.ip_forward=1)
15 # * Docker is installed and can be found in the user's path
16 # * Docker can be run as a non-root user
17 # - TODO: put the user in the docker group if necessary
18 # - TODO: mount cgroup automatically
19 # - TODO: start the docker service if not started
21 docker_path = %x(which docker.io).chomp
24 docker_path = %x(which docker).chomp
28 warn "Docker not found."
30 warn "Please make sure that Docker has been installed and"
31 warn "can be found in your PATH."
33 warn "Installation instructions for a variety of platforms can be found at"
34 warn "http://docs.docker.io/en/latest/installation/"
36 elsif not docker_ok? docker_path
37 warn "WARNING: docker could not be run."
38 warn "Please make sure that:"
39 warn " * You have permission to read and write /var/run/docker.sock"
40 warn " * a 'cgroup' volume is mounted on your machine"
41 warn " * the docker daemon is running"
45 # Check that debootstrap is installed.
46 if not debootstrap_ok?
47 warn "Installing debootstrap."
48 sudo '/usr/bin/apt-get', 'install', 'debootstrap'
51 # Generate a config.yml if it does not exist or is empty
52 if not File.size? 'config.yml'
53 print "Generating config.yml.\n"
54 print "Arvados needs to know the email address of the administrative user,\n"
55 print "so that when that user logs in they are automatically made an admin.\n"
56 print "This should be an email address associated with a Google account.\n"
58 admin_email_address = ""
59 until is_valid_email? admin_email_address
60 print "Enter your Google ID email address here: "
61 admin_email_address = gets.strip
62 if not is_valid_email? admin_email_address
63 print "That doesn't look like a valid email address. Please try again.\n"
67 print "Arvados needs to know the shell login name for the administrative user.\n"
68 print "This will also be used as the name for your git repository.\n"
71 until is_valid_user_name? user_name
72 print "Enter a shell login name here: "
73 user_name = gets.strip
74 if not is_valid_user_name? user_name
75 print "That doesn't look like a valid shell login name. Please try again.\n"
79 File.open 'config.yml', 'w' do |config_out|
80 config_out.write "# If a _PW or _SECRET variable is set to an empty string, a password\n"
81 config_out.write "# will be chosen randomly at build time. This is the\n"
82 config_out.write "# recommended setting.\n\n"
83 config = YAML.load_file 'config.yml.example'
84 config['API_AUTO_ADMIN_USER'] = admin_email_address
85 config['ARVADOS_USER_NAME'] = user_name
86 config['API_HOSTNAME'] = generate_api_hostname
87 config['API_WORKBENCH_ADDRESS'] = 'false'
88 config['PUBLIC_KEY_PATH'] = find_or_create_ssh_key(config['API_HOSTNAME'])
89 config.each_key do |var|
90 config_out.write "#{var}: #{config[var]}\n"
95 # If all prerequisites are met, go ahead and build.
96 if ip_forwarding_enabled? and
97 docker_ok? docker_path and
99 File.exists? 'config.yml'
107 # Execute the arg list 'cmd' under sudo.
108 # cmd can be passed either as a series of arguments or as a
109 # single argument consisting of a list, e.g.:
110 # sudo 'apt-get', 'update'
111 # sudo(['/usr/bin/gpasswd', '-a', ENV['USER'], 'docker'])
112 # sudo %w(/usr/bin/apt-get install lxc-docker)
115 # user can pass a single list in as an argument
116 # to allow usage like: sudo %w(apt-get install foo)
117 warn "You may need to enter your password here."
118 if cmd.length == 1 and cmd[0].class == Array
121 system '/usr/bin/sudo', *cmd
125 # Returns true if its arg looks like a valid email address.
126 # This is a very very loose sanity check.
128 def is_valid_email? str
129 str.match /^\S+@\S+\.\S+$/
132 # is_valid_user_name?
133 # Returns true if its arg looks like a valid unix username.
134 # This is a very very loose sanity check.
136 def is_valid_user_name? str
137 # borrowed from Debian's adduser (version 3.110)
138 str.match /^[_.A-Za-z0-9][-\@_.A-Za-z0-9]*\$?$/
141 # generate_api_hostname
142 # Generates a 5-character randomly chosen API hostname.
144 def generate_api_hostname
145 rand(2**256).to_s(36)[0...5]
148 # ip_forwarding_enabled?
149 # Returns 'true' if IP forwarding is enabled in the kernel
151 def ip_forwarding_enabled?
152 %x(/sbin/sysctl -n net.ipv4.ip_forward) == "1\n"
156 # Returns 'true' if debootstrap is installed and working.
159 return system '/usr/sbin/debootstrap --version > /dev/null 2>&1'
163 # Returns 'true' if docker can be run as the current user.
165 def docker_ok?(docker_path)
166 return system "#{docker_path} images > /dev/null 2>&1"
169 # find_or_create_ssh_key arvados_name
170 # Returns the SSH public key appropriate for this Arvados instance,
171 # generating one if necessary.
173 def find_or_create_ssh_key arvados_name
174 ssh_key_file = "#{ENV['HOME']}/.ssh/arvados_#{arvados_name}_id_rsa"
175 unless File.exists? ssh_key_file
178 '-C', "arvados@#{arvados_name}",
182 return "#{ssh_key_file}.pub"
186 # Determines which Docker package is suitable for this Linux distro
187 # and installs it, resolving any dependencies.
188 # NOTE: not in use yet.
191 linux_distro = %x(lsb_release --id).split.last
192 linux_release = %x(lsb_release --release).split.last
193 linux_version = linux_distro + " " + linux_release
194 kernel_release = `uname -r`
198 if not linux_release.match '^1[234]\.'
199 warn "Arvados requires at least Ubuntu 12.04 (Precise Pangolin)."
200 warn "Your system is Ubuntu #{linux_release}."
203 if linux_release.match '^12' and kernel_release.start_with? '3.2'
204 # Ubuntu Precise ships with a 3.2 kernel and must be upgraded.
205 warn "Your kernel #{kernel_release} must be upgraded to run Docker."
207 warn " sudo apt-get update"
208 warn " sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring"
213 sudo 'apt-get', 'update'
214 sudo 'apt-get', 'install', "linux-image-extra-#{kernel_release}"
217 # add Docker repository
218 sudo %w(/usr/bin/apt-key adv
219 --keyserver keyserver.ubuntu.com
220 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9)
221 source_file = Tempfile.new('arv')
222 source_file.write("deb http://get.docker.io/ubuntu docker main\n")
224 sudo '/bin/mv', source_file.path, '/etc/apt/sources.list.d/docker.list'
225 sudo %w(/usr/bin/apt-get update)
226 sudo %w(/usr/bin/apt-get install lxc-docker)
228 # Set up for non-root access
229 sudo %w(/usr/sbin/groupadd docker)
230 sudo '/usr/bin/gpasswd', '-a', ENV['USER'], 'docker'
231 sudo %w(/usr/sbin/service docker restart)
234 warn "Must be running a Debian or Ubuntu release in order to run Docker."
240 if __FILE__ == $PROGRAM_NAME
241 options = { :makefile => File.join(File.dirname(__FILE__), 'Makefile') }
242 OptionParser.new do |opts|
243 opts.on('-m', '--makefile MAKEFILE-PATH',
244 'Path to the Makefile used to build Arvados Docker images') do |mk|
245 options[:makefile] = mk