blob: f63d3a22f3ed83315305f18cc18b949571989258 [file] [log] [blame]
Brian Harringb938c782012-02-29 15:14:38 -08001#!/usr/bin/env python
Mike Frysinger2de7f042012-07-10 04:45:03 -04002# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Brian Harringb938c782012-02-29 15:14:38 -08003# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""This script fetches and prepares an SDK chroot.
7"""
8
Brian Harringb938c782012-02-29 15:14:38 -08009import os
Brian Harringb938c782012-02-29 15:14:38 -080010import urlparse
11
12from chromite.buildbot import constants
Brian Harringcfe762a2012-02-29 13:03:53 -080013from chromite.lib import cgroups
Brian Harringb6cf9142012-09-01 20:43:17 -070014from chromite.lib import commandline
Brian Harringb938c782012-02-29 15:14:38 -080015from chromite.lib import cros_build_lib
Brian Harringb938c782012-02-29 15:14:38 -080016from chromite.lib import locking
Brian Harringae0a5322012-09-15 01:46:51 -070017from chromite.lib import osutils
Brian Harringcfe762a2012-02-29 13:03:53 -080018from chromite.lib import sudo
Brian Harringb938c782012-02-29 15:14:38 -080019
20cros_build_lib.STRICT_SUDO = True
21
22
23DEFAULT_URL = 'https://commondatastorage.googleapis.com/chromiumos-sdk/'
Zdenek Behanfd0efe42012-04-13 04:36:40 +020024SDK_SUFFIXES = ['.tbz2', '.tar.xz']
25
Brian Harringb938c782012-02-29 15:14:38 -080026SRC_ROOT = os.path.realpath(constants.SOURCE_ROOT)
Brian Harringb938c782012-02-29 15:14:38 -080027OVERLAY_DIR = os.path.join(SRC_ROOT, 'src/third_party/chromiumos-overlay')
28SDK_VERSION_FILE = os.path.join(OVERLAY_DIR,
29 'chromeos/binhost/host/sdk_version.conf')
30
31# TODO(zbehan): Remove the dependency on these, reimplement them in python
32MAKE_CHROOT = [os.path.join(SRC_ROOT, 'src/scripts/sdk_lib/make_chroot.sh')]
33ENTER_CHROOT = [os.path.join(SRC_ROOT, 'src/scripts/sdk_lib/enter_chroot.sh')]
34
35# We need these tools to run. Very common tools (tar,..) are ommited.
36NEEDED_TOOLS = ['curl']
37
38def GetHostArch():
39 """Returns a string for the host architecture"""
40 out = cros_build_lib.RunCommand(['uname', '-m'],
41 redirect_stdout=True, print_cmd=False).output
42 return out.rstrip('\n')
43
44def CheckPrerequisites(needed_tools):
45 """Verifies that the required tools are present on the system.
46
47 This is especially important as this script is intended to run
48 outside the chroot.
49
50 Arguments:
51 needed_tools: an array of string specified binaries to look for.
52
53 Returns:
54 True if all needed tools were found.
55 """
Brian Harring98b54902012-03-23 04:05:42 -070056 missing = []
Brian Harringb938c782012-02-29 15:14:38 -080057 for tool in needed_tools:
58 cmd = ['which', tool]
59 try:
60 cros_build_lib.RunCommand(cmd, print_cmd=False, redirect_stdout=True,
61 combine_stdout_stderr=True)
62 except cros_build_lib.RunCommandError:
Brian Harring98b54902012-03-23 04:05:42 -070063 missing.append(tool)
64 return missing
65
Brian Harringb938c782012-02-29 15:14:38 -080066
67def GetLatestVersion():
68 """Extracts latest version from chromiumos-overlay."""
69 sdk_file = open(SDK_VERSION_FILE)
70 buf = sdk_file.readline().rstrip('\n').split('=')
71 if buf[0] != 'SDK_LATEST_VERSION':
72 raise Exception('Malformed version file')
73 return buf[1].strip('"')
74
75
Zdenek Behanfd0efe42012-04-13 04:36:40 +020076def GetArchStageTarballs(tarballArch, version):
Brian Harringb938c782012-02-29 15:14:38 -080077 """Returns the URL for a given arch/version"""
78 D = { 'x86_64': 'cros-sdk-' }
79 try:
Zdenek Behanfd0efe42012-04-13 04:36:40 +020080 return [DEFAULT_URL + D[tarballArch] + version + x for x in SDK_SUFFIXES]
Brian Harringb938c782012-02-29 15:14:38 -080081 except KeyError:
Brian Harring98b54902012-03-23 04:05:42 -070082 raise SystemExit('Unsupported arch: %s' % (tarballArch,))
Brian Harringb938c782012-02-29 15:14:38 -080083
84
Brian Harringae0a5322012-09-15 01:46:51 -070085def FetchRemoteTarballs(storage_dir, urls):
Zdenek Behanfd0efe42012-04-13 04:36:40 +020086 """Fetches a tarball given by url, and place it in sdk/.
87
88 Args:
89 urls: List of URLs to try to download. Download will stop on first success.
90
91 Returns:
92 Full path to the downloaded file
93 """
Zdenek Behanfd0efe42012-04-13 04:36:40 +020094 def RemoteTarballExists(url):
95 """Tests if a remote tarball exists."""
96 # We also use this for "local" tarballs using file:// urls. Those will
97 # fail the -I check, so just check the file locally instead.
98 if url.startswith('file://'):
99 return os.path.exists(url.replace('file://', ''))
100
Ryan Cui3045c5d2012-07-13 18:00:33 -0700101 result = cros_build_lib.RunCurl(['-I', url],
102 redirect_stdout=True, redirect_stderr=True,
103 print_cmd=False)
Bernie Thompsone522add2012-05-29 12:47:12 -0700104 # We must walk the output to find the string '200 OK' for use cases where
105 # a proxy is involved and may have pushed down the actual header.
106 for header in result.output.splitlines():
107 if header.find('200 OK') != -1:
108 return 1
109 return 0
110
Zdenek Behanfd0efe42012-04-13 04:36:40 +0200111
112 url = None
113 for url in urls:
114 print 'Attempting download: %s' % url
115 if RemoteTarballExists(url):
116 break
117 else:
118 raise Exception('No valid URLs found!')
119
Brian Harringb45afea2012-05-17 08:10:53 -0700120 # pylint: disable=E1101
Zdenek Behanb2fa72e2012-03-16 04:49:30 +0100121 tarball_name = os.path.basename(urlparse.urlparse(url).path)
Brian Harringae0a5322012-09-15 01:46:51 -0700122 tarball_dest = os.path.join(storage_dir, tarball_name)
Zdenek Behanb2fa72e2012-03-16 04:49:30 +0100123
124 # Cleanup old tarballs.
Brian Harringae0a5322012-09-15 01:46:51 -0700125 files_to_delete = [f for f in os.listdir(storage_dir) if f != tarball_name]
Zdenek Behanb2fa72e2012-03-16 04:49:30 +0100126 if files_to_delete:
127 print 'Cleaning up old tarballs: ' + str(files_to_delete)
128 for f in files_to_delete:
Brian Harringae0a5322012-09-15 01:46:51 -0700129 f_path = os.path.join(storage_dir, f)
Zdenek Behanb2fa72e2012-03-16 04:49:30 +0100130 # Only delete regular files that belong to us.
131 if os.path.isfile(f_path) and os.stat(f_path).st_uid == os.getuid():
132 os.remove(f_path)
Brian Harringb938c782012-02-29 15:14:38 -0800133
Brian Harringb45afea2012-05-17 08:10:53 -0700134 curl_opts = ['-f', '-L', '-y', '30', '--output', tarball_dest]
Brian Harringb938c782012-02-29 15:14:38 -0800135 if not url.startswith('file://') and os.path.exists(tarball_dest):
136 # Only resume for remote URLs. If the file is local, there's no
137 # real speedup, and using the same filename for different files
138 # locally will cause issues.
Zdenek Behan9c644dd2012-04-05 06:24:02 +0200139 curl_opts.extend(['-C', '-'])
Brian Harringb938c782012-02-29 15:14:38 -0800140
141 # Additionally, certain versions of curl incorrectly fail if
142 # told to resume a file that is fully downloaded, thus do a
143 # check on our own.
144 # see:
Brian Harringb45afea2012-05-17 08:10:53 -0700145 # pylint: disable=C0301
Brian Harringb938c782012-02-29 15:14:38 -0800146 # https://sourceforge.net/tracker/?func=detail&atid=100976&aid=3482927&group_id=976
Ryan Cui3045c5d2012-07-13 18:00:33 -0700147 result = cros_build_lib.RunCurl(['-I', url],
148 redirect_stdout=True,
149 redirect_stderr=True,
150 print_cmd=False)
Zdenek Behan9c644dd2012-04-05 06:24:02 +0200151
Brian Harringb938c782012-02-29 15:14:38 -0800152 for x in result.output.splitlines():
153 if x.lower().startswith("content-length:"):
154 length = int(x.split(":", 1)[-1].strip())
155 if length == os.path.getsize(tarball_dest):
156 # Fully fetched; bypass invoking curl, since it can screw up handling
157 # of this (>=7.21.4 and up).
158 return tarball_dest
159 break
Zdenek Behan9c644dd2012-04-05 06:24:02 +0200160 curl_opts.append(url)
Ryan Cui3045c5d2012-07-13 18:00:33 -0700161 cros_build_lib.RunCurl(curl_opts)
Brian Harringb938c782012-02-29 15:14:38 -0800162 return tarball_dest
163
164
Brian Harringae0a5322012-09-15 01:46:51 -0700165def BootstrapChroot(chroot_path, cache_dir, stage_url, replace):
Brian Harringb938c782012-02-29 15:14:38 -0800166 """Builds a new chroot from source"""
167 cmd = MAKE_CHROOT + ['--chroot', chroot_path,
Brian Harringae0a5322012-09-15 01:46:51 -0700168 '--nousepkg',
169 '--cache_dir', cache_dir]
Brian Harringb938c782012-02-29 15:14:38 -0800170
171 stage = None
172 if stage_url:
Brian Harringae0a5322012-09-15 01:46:51 -0700173 stage = FetchRemoteTarballs(os.path.join(cache_dir, 'sdks'),
174 [stage_url])
Brian Harringb938c782012-02-29 15:14:38 -0800175
176 if stage:
177 cmd.extend(['--stage3_path', stage])
178
179 if replace:
180 cmd.append('--replace')
181
182 try:
183 cros_build_lib.RunCommand(cmd, print_cmd=False)
184 except cros_build_lib.RunCommandError:
Brian Harring98b54902012-03-23 04:05:42 -0700185 raise SystemExit('Running %r failed!' % cmd)
Brian Harringb938c782012-02-29 15:14:38 -0800186
187
Brian Harringae0a5322012-09-15 01:46:51 -0700188def CreateChroot(sdk_url, cache_dir, sdk_version, chroot_path,
189 replace, nousepkg):
Brian Harringb938c782012-02-29 15:14:38 -0800190 """Creates a new chroot from a given SDK"""
Brian Harringb938c782012-02-29 15:14:38 -0800191
192 # Based on selections, fetch the tarball
193 if sdk_url:
Zdenek Behanfd0efe42012-04-13 04:36:40 +0200194 urls = [sdk_url]
Brian Harringb938c782012-02-29 15:14:38 -0800195 else:
196 arch = GetHostArch()
Zdenek Behanfd0efe42012-04-13 04:36:40 +0200197 urls = GetArchStageTarballs(arch, sdk_version)
Brian Harringb938c782012-02-29 15:14:38 -0800198
Brian Harringae0a5322012-09-15 01:46:51 -0700199 sdk = FetchRemoteTarballs(os.path.join(cache_dir, 'sdks'), urls)
Brian Harringb938c782012-02-29 15:14:38 -0800200
201 # TODO(zbehan): Unpack and install
202 # For now, we simply call make_chroot on the prebuilt chromeos-sdk.
203 # make_chroot provides a variety of hacks to make the chroot useable.
204 # These should all be eliminated/minimised, after which, we can change
205 # this to just unpacking the sdk.
206 cmd = MAKE_CHROOT + ['--stage3_path', sdk,
Brian Harringae0a5322012-09-15 01:46:51 -0700207 '--chroot', chroot_path,
208 '--cache_dir', cache_dir]
Mike Frysinger2de7f042012-07-10 04:45:03 -0400209 if nousepkg:
210 cmd.append('--nousepkg')
Brian Harringb938c782012-02-29 15:14:38 -0800211 if replace:
212 cmd.append('--replace')
213
214 try:
215 cros_build_lib.RunCommand(cmd, print_cmd=False)
216 except cros_build_lib.RunCommandError:
Brian Harring98b54902012-03-23 04:05:42 -0700217 raise SystemExit('Running %r failed!' % cmd)
Brian Harringb938c782012-02-29 15:14:38 -0800218
219
220def DeleteChroot(chroot_path):
221 """Deletes an existing chroot"""
222 cmd = MAKE_CHROOT + ['--chroot', chroot_path,
223 '--delete']
224 try:
225 cros_build_lib.RunCommand(cmd, print_cmd=False)
226 except cros_build_lib.RunCommandError:
Brian Harring98b54902012-03-23 04:05:42 -0700227 raise SystemExit('Running %r failed!' % cmd)
Brian Harringb938c782012-02-29 15:14:38 -0800228
229
230def _CreateLockFile(path):
Zdenek Behanfd0efe42012-04-13 04:36:40 +0200231 """Create a lockfile via sudo that is writable by current user."""
232 cros_build_lib.SudoRunCommand(['touch', path], print_cmd=False)
233 cros_build_lib.SudoRunCommand(['chown', str(os.getuid()), path],
234 print_cmd=False)
235 cros_build_lib.SudoRunCommand(['chmod', '644', path], print_cmd=False)
Brian Harringb938c782012-02-29 15:14:38 -0800236
237
Brian Harringae0a5322012-09-15 01:46:51 -0700238def EnterChroot(chroot_path, cache_dir, chrome_root, chrome_root_mount,
239 additional_args):
Brian Harringb938c782012-02-29 15:14:38 -0800240 """Enters an existing SDK chroot"""
Brian Harringae0a5322012-09-15 01:46:51 -0700241 cmd = ENTER_CHROOT + ['--chroot', chroot_path, '--cache_dir', cache_dir]
Brian Harringb938c782012-02-29 15:14:38 -0800242 if chrome_root:
243 cmd.extend(['--chrome_root', chrome_root])
244 if chrome_root_mount:
245 cmd.extend(['--chrome_root_mount', chrome_root_mount])
246 if len(additional_args) > 0:
247 cmd.append('--')
248 cmd.extend(additional_args)
Brian Harring7199e7d2012-03-23 04:10:08 -0700249
250 ret = cros_build_lib.RunCommand(cmd, print_cmd=False, error_code_ok=True)
251 # If we were in interactive mode, ignore the exit code; it'll be whatever
252 # they last ran w/in the chroot and won't matter to us one way or another.
253 # Note this does allow chroot entrance to fail and be ignored during
254 # interactive; this is however a rare case and the user will immediately
255 # see it (nor will they be checking the exit code manually).
256 if ret.returncode != 0 and additional_args:
257 raise SystemExit('Running %r failed with exit code %i'
258 % (cmd, ret.returncode))
Brian Harringb938c782012-02-29 15:14:38 -0800259
260
Brian Harring6be2efc2012-03-01 05:04:00 -0800261def main(argv):
Brian Harringb938c782012-02-29 15:14:38 -0800262 # TODO(ferringb): make argv required once depot_tools is fixed.
Zdenek Behanfd0efe42012-04-13 04:36:40 +0200263 usage = """usage: %prog [options] [VAR1=val1 .. VARn=valn -- <args>]
Brian Harringb938c782012-02-29 15:14:38 -0800264
265This script manages a local CrOS SDK chroot. Depending on the flags,
266it can download, build or enter a chroot.
267
268Action taken is the following:
269--enter (default) .. Installs and enters a chroot
270--download .. Just download a chroot (enter if combined with --enter)
Brian Harringb938c782012-02-29 15:14:38 -0800271--delete .. Removes a chroot
272"""
273 sdk_latest_version = GetLatestVersion()
Brian Harringae0a5322012-09-15 01:46:51 -0700274 parser = commandline.OptionParser(usage, caching=True)
Brian Harringb938c782012-02-29 15:14:38 -0800275 # Actions:
Brian Harring0ebc33c2012-05-25 13:36:19 -0700276 parser.add_option('--bootstrap',
Brian Harringb938c782012-02-29 15:14:38 -0800277 action='store_true', dest='bootstrap', default=False,
Brian Harring6ed482a2012-08-21 18:01:44 -0700278 help=('Build everything from scratch, including the sdk. '
279 'Use this only if you need to validate a change '
280 'that affects SDK creation itself (toolchain and '
281 'build are typically the only folk who need this). '
282 'Note this will quite heavily slow down the build. '
283 'Finally, this option implies --enter.'))
Brian Harring0ebc33c2012-05-25 13:36:19 -0700284 parser.add_option('--delete',
Brian Harringb938c782012-02-29 15:14:38 -0800285 action='store_true', dest='delete', default=False,
286 help=('Delete the current SDK chroot'))
Brian Harring0ebc33c2012-05-25 13:36:19 -0700287 parser.add_option('--download',
Brian Harringb938c782012-02-29 15:14:38 -0800288 action='store_true', dest='download', default=False,
289 help=('Download and install a prebuilt SDK'))
Brian Harring0ebc33c2012-05-25 13:36:19 -0700290 parser.add_option('--enter',
Brian Harringb938c782012-02-29 15:14:38 -0800291 action='store_true', dest='enter', default=False,
292 help=('Enter the SDK chroot, possibly (re)create first'))
293
294 # Global options:
Brian Harringb6cf9142012-09-01 20:43:17 -0700295 default_chroot = os.path.join(SRC_ROOT, constants.DEFAULT_CHROOT_DIR)
296 parser.add_option('--chroot', dest='chroot', default=default_chroot,
297 type='path',
Brian Harringb938c782012-02-29 15:14:38 -0800298 help=('SDK chroot dir name [%s]' %
299 constants.DEFAULT_CHROOT_DIR))
300
301 # Additional options:
Brian Harring0ebc33c2012-05-25 13:36:19 -0700302 parser.add_option('--chrome_root',
Brian Harringb6cf9142012-09-01 20:43:17 -0700303 dest='chrome_root', default=None, type='path',
Brian Harringb938c782012-02-29 15:14:38 -0800304 help=('Mount this chrome root into the SDK chroot'))
Brian Harring0ebc33c2012-05-25 13:36:19 -0700305 parser.add_option('--chrome_root_mount',
Brian Harringb6cf9142012-09-01 20:43:17 -0700306 dest='chrome_root_mount', default=None, type='path',
Brian Harringb938c782012-02-29 15:14:38 -0800307 help=('Mount chrome into this path inside SDK chroot'))
308 parser.add_option('-r', '--replace',
309 action='store_true', dest='replace', default=False,
310 help=('Replace an existing SDK chroot'))
Mike Frysinger2de7f042012-07-10 04:45:03 -0400311 parser.add_option('--nousepkg',
312 action='store_true', dest='nousepkg', default=False,
313 help=('Do not use binary packages when creating a chroot'))
Brian Harringb938c782012-02-29 15:14:38 -0800314 parser.add_option('-u', '--url',
Brian Harringb6cf9142012-09-01 20:43:17 -0700315 dest='sdk_url', default=None,
Brian Harringb938c782012-02-29 15:14:38 -0800316 help=('''Use sdk tarball located at this url.
317 Use file:// for local files.'''))
318 parser.add_option('-v', '--version',
Brian Harringb6cf9142012-09-01 20:43:17 -0700319 dest='sdk_version', default=None,
Brian Harringb938c782012-02-29 15:14:38 -0800320 help=('Use this sdk version [%s]' % sdk_latest_version))
321 (options, remaining_arguments) = parser.parse_args(argv)
322
323 # Some sanity checks first, before we ask for sudo credentials.
324 if cros_build_lib.IsInsideChroot():
Brian Harring98b54902012-03-23 04:05:42 -0700325 parser.error("This needs to be ran outside the chroot")
Brian Harringb938c782012-02-29 15:14:38 -0800326
Brian Harring98b54902012-03-23 04:05:42 -0700327 missing = CheckPrerequisites(NEEDED_TOOLS)
328 if missing:
329 parser.error((
330 'The tool(s) %s were not found.'
331 'Please install the appropriate package in your host.'
332 'Example(ubuntu):'
333 ' sudo apt-get install <packagename>'
334 % (', '.join(missing))))
Brian Harringb938c782012-02-29 15:14:38 -0800335
336 # Default action is --enter, if no other is selected.
337 if not (options.bootstrap or options.download or options.delete):
338 options.enter = True
339
340 # Only --enter can process additional args as passthrough commands.
341 # Warn and exit for least surprise.
342 if len(remaining_arguments) > 0 and not options.enter:
Brian Harring98b54902012-03-23 04:05:42 -0700343 parser.error("Additional arguments are not permitted, unless running "
344 "with --enter")
Brian Harringb938c782012-02-29 15:14:38 -0800345
346 # Some actions can be combined, as they merely modify how is the chroot
347 # going to be made. The only option that hates all others is --delete.
348 if options.delete and \
349 (options.enter or options.download or options.bootstrap):
Brian Harring98b54902012-03-23 04:05:42 -0700350 parser.error("--delete cannot be combined with --enter, "
351 "--download or --bootstrap")
Brian Harringb938c782012-02-29 15:14:38 -0800352 # NOTE: --delete is a true hater, it doesn't like other options either, but
353 # those will hardly lead to confusion. Nobody can expect to pass --version to
354 # delete and actually change something.
355
356 if options.bootstrap and options.download:
Brian Harring98b54902012-03-23 04:05:42 -0700357 parser.error("Either --bootstrap or --download, not both")
Brian Harringb938c782012-02-29 15:14:38 -0800358
359 # Bootstrap will start off from a non-selectable stage3 tarball. Attempts to
360 # select sdk by version are confusing. Warn and exit. We can still specify a
361 # tarball by path or URL though.
362 if options.bootstrap and options.sdk_version:
Brian Harring98b54902012-03-23 04:05:42 -0700363 parser.error("Cannot use --version when bootstrapping")
Brian Harringb938c782012-02-29 15:14:38 -0800364
Brian Harringb938c782012-02-29 15:14:38 -0800365 if not options.sdk_version:
366 sdk_version = sdk_latest_version
367 else:
368 sdk_version = options.sdk_version
369
Brian Harringb6cf9142012-09-01 20:43:17 -0700370 if options.delete and not os.path.exists(options.chroot):
Brian Harringb938c782012-02-29 15:14:38 -0800371 print "Not doing anything. The chroot you want to remove doesn't exist."
Brian Harring98b54902012-03-23 04:05:42 -0700372 return 0
Brian Harringb938c782012-02-29 15:14:38 -0800373
Brian Harringb6cf9142012-09-01 20:43:17 -0700374 lock_path = os.path.dirname(options.chroot)
Brian Harringb938c782012-02-29 15:14:38 -0800375 lock_path = os.path.join(lock_path,
Brian Harringb6cf9142012-09-01 20:43:17 -0700376 '.%s_lock' % os.path.basename(options.chroot))
David James891dccf2012-08-20 14:19:54 -0700377 with sudo.SudoKeepAlive(ttyless_sudo=False):
Brian Harring4e6412d2012-03-09 20:54:02 -0800378 with cgroups.SimpleContainChildren('cros_sdk'):
Brian Harringcfe762a2012-02-29 13:03:53 -0800379 _CreateLockFile(lock_path)
380 with locking.FileLock(lock_path, 'chroot lock') as lock:
381 if options.delete:
382 lock.write_lock()
Brian Harringb6cf9142012-09-01 20:43:17 -0700383 DeleteChroot(options.chroot)
Brian Harring98b54902012-03-23 04:05:42 -0700384 return 0
Brian Harringb938c782012-02-29 15:14:38 -0800385
Brian Harringae0a5322012-09-15 01:46:51 -0700386 sdk_cache = os.path.join(options.cache_dir, 'sdks')
387 distfiles_cache = os.path.join(options.cache_dir, 'distfiles')
388
389 for target in (sdk_cache, distfiles_cache):
390 src = os.path.join(SRC_ROOT, os.path.basename(target))
391 if not os.path.exists(src):
392 osutils.SafeMakedirs(target)
393 continue
394
395 lock.write_lock(
396 "Upgrade to %r needed but chroot is locked; please exit "
397 "all instances so this upgrade can finish." % src)
398 if not os.path.exists(src):
399 # Note that while waiting for the write lock, src may've vanished;
400 # it's a rare race during the upgrade process that's a byproduct
401 # of us avoiding taking a write lock to do the src check. If we
402 # took a write lock for that check, it would effectively limit
403 # all cros_sdk for a chroot to a single instance.
404 osutils.SafeMakedirs(target)
405 elif not os.path.exists(target):
406 # Upgrade occurred, but a reversion, or something whacky
407 # occurred writing to the old location. Wipe and continue.
408 cros_build_lib.SudoRunCommand(
409 ['mv', '--', src, target], print_cmd=False)
410 else:
411 # Upgrade occurred once already, but either a reversion or
412 # some before/after separate cros_sdk usage is at play.
413 # Wipe and continue.
414 osutils.RmDir(src, sudo=True)
415
Brian Harringcfe762a2012-02-29 13:03:53 -0800416 # Print a suggestion for replacement, but not if running just --enter.
Brian Harringb6cf9142012-09-01 20:43:17 -0700417 if os.path.exists(options.chroot) and not options.replace and \
Brian Harringcfe762a2012-02-29 13:03:53 -0800418 (options.bootstrap or options.download):
419 print "Chroot already exists. Run with --replace to re-create."
Brian Harringb938c782012-02-29 15:14:38 -0800420
Brian Harringcfe762a2012-02-29 13:03:53 -0800421 # Chroot doesn't exist or asked to replace.
Brian Harringb6cf9142012-09-01 20:43:17 -0700422 if not os.path.exists(options.chroot) or options.replace:
Brian Harringcfe762a2012-02-29 13:03:53 -0800423 lock.write_lock()
424 if options.bootstrap:
Brian Harringae0a5322012-09-15 01:46:51 -0700425 BootstrapChroot(options.chroot, options.cache_dir,
426 options.sdk_url, options.replace)
Brian Harringcfe762a2012-02-29 13:03:53 -0800427 else:
Brian Harringae0a5322012-09-15 01:46:51 -0700428 CreateChroot(options.sdk_url, options.cache_dir,
429 sdk_version, options.chroot, options.replace,
430 options.nousepkg)
Brian Harringcfe762a2012-02-29 13:03:53 -0800431 if options.enter:
432 lock.read_lock()
Brian Harringae0a5322012-09-15 01:46:51 -0700433 EnterChroot(options.chroot, options.cache_dir, options.chrome_root,
Brian Harringcfe762a2012-02-29 13:03:53 -0800434 options.chrome_root_mount, remaining_arguments)