blob: 41713be822c9a616dcaaca19551c40aabede2ab8 [file] [log] [blame]
Wei-Han Chene97d3532016-03-31 19:22:01 +08001#!/usr/bin/env python
Wei-Han Chene97d3532016-03-31 19:22:01 +08002# Copyright 2016 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
Joel Kitching679a00b2016-08-03 11:42:58 +08006"""Transition to release state directly without reboot."""
Wei-Han Chene97d3532016-03-31 19:22:01 +08007
Wei-Han Chenbe1355a2016-04-24 19:31:03 +08008import json
Wei-Han Chene97d3532016-03-31 19:22:01 +08009import logging
Wei-Han Chene97d3532016-03-31 19:22:01 +080010import os
Shun-Hsing Oub5724832016-07-21 11:45:58 +080011import re
Wei-Han Chene97d3532016-03-31 19:22:01 +080012import resource
13import shutil
14import signal
Wei-Han Chenbe1355a2016-04-24 19:31:03 +080015import socket
Wei-Han Chene97d3532016-03-31 19:22:01 +080016import tempfile
17import textwrap
18import time
19
20import factory_common # pylint: disable=unused-import
21from cros.factory.gooftool import chroot
Wei-Han Chen0a3320e2016-04-23 01:32:07 +080022from cros.factory.gooftool.common import ExecFactoryPar
Wei-Han Chen9adf9de2016-04-01 19:35:41 +080023from cros.factory.gooftool.common import Util
Wei-Han Chen0a3320e2016-04-23 01:32:07 +080024from cros.factory.test.env import paths
Wei-Han Chene97d3532016-03-31 19:22:01 +080025from cros.factory.utils import process_utils
26from cros.factory.utils import sync_utils
27from cros.factory.utils import sys_utils
28
29
Hung-Te Lina3195462016-10-14 15:48:29 +080030"""Directory of scripts for device cut-off"""
31CUTOFF_SCRIPT_DIR = '/usr/local/factory/sh/cutoff'
Wei-Han Chen9adf9de2016-04-01 19:35:41 +080032
Wei-Han Chenbe1355a2016-04-24 19:31:03 +080033WIPE_IN_TMPFS_LOG = 'wipe_in_tmpfs.log'
Wei-Han Chene97d3532016-03-31 19:22:01 +080034
Joel Kitching679a00b2016-08-03 11:42:58 +080035
Wei-Han Chenbe1355a2016-04-24 19:31:03 +080036def _CopyLogFileToStateDev(state_dev, logfile):
Wei-Han Chene97d3532016-03-31 19:22:01 +080037 with sys_utils.MountPartition(state_dev,
38 rw=True,
39 fstype='ext4') as mount_point:
40 shutil.copyfile(logfile,
41 os.path.join(mount_point, os.path.basename(logfile)))
42
43
Wei-Han Chenbe1355a2016-04-24 19:31:03 +080044def _OnError(ip, port, token, state_dev, wipe_in_tmpfs_log=None,
45 wipe_init_log=None):
46 if wipe_in_tmpfs_log:
47 _CopyLogFileToStateDev(state_dev, wipe_in_tmpfs_log)
48 if wipe_init_log:
49 _CopyLogFileToStateDev(state_dev, wipe_init_log)
50 _InformStation(ip, port, token,
51 wipe_in_tmpfs_log=wipe_in_tmpfs_log,
52 wipe_init_log=wipe_init_log,
53 success=False)
54
55
Wei-Han Chene97d3532016-03-31 19:22:01 +080056def Daemonize(logfile=None):
57 """Starts a daemon process and terminates current process.
58
You-Cheng Syu461ec032017-03-06 15:56:58 +080059 A daemon process will be started, and continue executing the following codes.
Wei-Han Chene97d3532016-03-31 19:22:01 +080060 The original process that calls this function will be terminated.
61
62 Example::
63
64 def DaemonFunc():
65 Daemonize()
66 # the process calling DaemonFunc is terminated.
67 # the following codes will be executed in a daemon process
68 ...
69
70 If you would like to keep the original process alive, you could fork a child
71 process and let child process start the daemon.
72 """
73 # fork from parent process
74 if os.fork():
75 # stop parent process
76 os._exit(0) # pylint: disable=protected-access
77
78 # decouple from parent process
79 os.chdir('/')
80 os.umask(0)
81 os.setsid()
82
83 # fork again
84 if os.fork():
85 os._exit(0) # pylint: disable=protected-access
86
87 maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
88 if maxfd == resource.RLIM_INFINITY:
89 maxfd = 1024
90
91 for fd in xrange(maxfd):
92 try:
93 os.close(fd)
94 except OSError:
95 pass
96
97 # Reopen fd 0 (stdin), 1 (stdout), 2 (stderr) to prevent errors from reading
98 # or writing to these files.
99 # Since we have closed all file descriptors, os.open should open a file with
100 # file descriptor equals to 0
101 os.open('/dev/null', os.O_RDWR)
102 if logfile is None:
103 os.dup2(0, 1) # stdout
104 os.dup2(0, 2) # stderr
105 else:
106 os.open(logfile, os.O_RDWR | os.O_CREAT)
107 os.dup2(1, 2) # stderr
108
109
110def ResetLog(logfile=None):
111 if len(logging.getLogger().handlers) > 0:
112 for handler in logging.getLogger().handlers:
113 logging.getLogger().removeHandler(handler)
114 logging.basicConfig(filename=logfile, level=logging.NOTSET)
115
116
Hung-Te Lin7b27f0c2016-10-18 18:41:29 +0800117def WipeInTmpFs(is_fast=None, shopfloor_url=None, station_ip=None,
118 station_port=None, wipe_finish_token=None):
You-Cheng Syu461ec032017-03-06 15:56:58 +0800119 """prepare to wipe by pivot root to tmpfs and unmount stateful partition.
Wei-Han Chene97d3532016-03-31 19:22:01 +0800120
121 Args:
122 is_fast: whether or not to apply fast wipe.
Wei-Han Chene97d3532016-03-31 19:22:01 +0800123 shopfloor_url: for inform_shopfloor.sh
124 """
125
Wei-Han Chene97d3532016-03-31 19:22:01 +0800126 Daemonize()
127
You-Cheng Syu461ec032017-03-06 15:56:58 +0800128 # Set the default umask.
Shun-Hsing Oub5724832016-07-21 11:45:58 +0800129 os.umask(0022)
130
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800131 logfile = os.path.join('/tmp', WIPE_IN_TMPFS_LOG)
Wei-Han Chene97d3532016-03-31 19:22:01 +0800132 ResetLog(logfile)
133
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800134 factory_par = paths.GetFactoryPythonArchivePath()
Wei-Han Chene97d3532016-03-31 19:22:01 +0800135
136 new_root = tempfile.mkdtemp(prefix='tmpfs.')
137 binary_deps = [
138 'activate_date', 'backlight_tool', 'busybox', 'cgpt', 'cgpt.bin',
139 'clobber-log', 'clobber-state', 'coreutils', 'crossystem', 'dd',
140 'display_boot_message', 'dumpe2fs', 'ectool', 'flashrom', 'halt',
141 'initctl', 'mkfs.ext4', 'mktemp', 'mosys', 'mount', 'mount-encrypted',
142 'od', 'pango-view', 'pkill', 'pv', 'python', 'reboot', 'setterm', 'sh',
Wei-Han Chen85ace052017-06-24 15:39:50 +0800143 'shutdown', 'stop', 'umount', 'vpd', 'curl', 'lsof', 'jq', '/sbin/frecon']
Wei-Han Chene97d3532016-03-31 19:22:01 +0800144
145 etc_issue = textwrap.dedent("""
146 You are now in tmp file system created for in-place wiping.
147
148 For debugging wiping fails, see log files under
149 /tmp
150 /mnt/stateful_partition/unencrypted
151
152 The log file name should be
153 - wipe_in_tmpfs.log
154 - wipe_init.log
155
156 You can also run scripts under /usr/local/factory/sh for wiping process.
157 """)
158
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800159 util = Util()
160
161 root_disk = util.GetPrimaryDevicePath()
162 release_rootfs = util.GetReleaseRootPartitionPath()
163 state_dev = util.GetPrimaryDevicePath(1)
Wei-Han Chene97d3532016-03-31 19:22:01 +0800164 wipe_args = 'factory' + (' fast' if is_fast else '')
165
166 logging.debug('state_dev: %s', state_dev)
167 logging.debug('factory_par: %s', factory_par)
168
169 old_root = 'old_root'
170
171 try:
Shun-Hsing Oub5724832016-07-21 11:45:58 +0800172 # pango load library module dynamically. Therefore we need to query it
173 # first.
174 pango_query_output = process_utils.SpawnOutput(
175 ['pango-querymodules', '--system'])
176 m = re.search(r'^# ModulesPath = (.+)$', pango_query_output, re.M)
177 assert m != None, 'Failed to find pango module path.'
178 pango_module = m.group(1)
179
Wei-Han Chene97d3532016-03-31 19:22:01 +0800180 with chroot.TmpChroot(
181 new_root,
182 file_dir_list=[
Shun-Hsing Oub5724832016-07-21 11:45:58 +0800183 # Basic rootfs.
Wei-Ning Huang71f94e12016-07-17 23:21:41 +0800184 '/bin', '/etc', '/lib', '/lib64', '/root', '/sbin',
Shun-Hsing Oub5724832016-07-21 11:45:58 +0800185 # Factory related scripts.
186 factory_par,
187 '/usr/local/factory/sh',
Wei-Han Chen85ace052017-06-24 15:39:50 +0800188 # Factory config files
189 '/usr/local/factory/py/config',
Shun-Hsing Oub5724832016-07-21 11:45:58 +0800190 # Fonts and assets required for showing message.
191 pango_module,
Wei-Han Chene97d3532016-03-31 19:22:01 +0800192 '/usr/share/fonts/notocjk',
193 '/usr/share/cache/fontconfig',
194 '/usr/share/chromeos-assets/images',
195 '/usr/share/chromeos-assets/text/boot_messages',
196 '/usr/share/misc/chromeos-common.sh',
Shun-Hsing Oub5724832016-07-21 11:45:58 +0800197 # File required for enable ssh connection.
198 '/mnt/stateful_partition/etc/ssh',
199 '/root/.ssh',
200 '/usr/share/chromeos-ssh-config',
201 # /var/empty is required by openssh server.
202 '/var/empty'],
Wei-Han Chene97d3532016-03-31 19:22:01 +0800203 binary_list=binary_deps, etc_issue=etc_issue).PivotRoot(old_root):
204 logging.debug(
205 'lsof: %s',
206 process_utils.SpawnOutput('lsof -p %d' % os.getpid(), shell=True))
207
Wei-Han Chene97d3532016-03-31 19:22:01 +0800208 process_utils.Spawn(['sync'], call=True)
209 time.sleep(3)
210
211 # Restart gooftool under new root. Since current gooftool might be using
212 # some resource under stateful partition, restarting gooftool ensures that
213 # everything new gooftool is using comes from tmpfs and we can safely
214 # unmount stateful partition.
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800215 args = []
216 if wipe_args:
217 args += ['--wipe_args', wipe_args]
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800218 if shopfloor_url:
219 args += ['--shopfloor_url', shopfloor_url]
220 if station_ip:
221 args += ['--station_ip', station_ip]
222 if station_port:
223 args += ['--station_port', station_port]
224 if wipe_finish_token:
225 args += ['--wipe_finish_token', wipe_finish_token]
226 args += ['--state_dev', state_dev]
227 args += ['--release_rootfs', release_rootfs]
228 args += ['--root_disk', root_disk]
229 args += ['--old_root', old_root]
230
231 ExecFactoryPar('gooftool', 'wipe_init', *args)
Wei-Han Chene97d3532016-03-31 19:22:01 +0800232 raise RuntimeError('Should not reach here')
Hung-Te Linc8174b52017-06-02 11:11:45 +0800233 except Exception:
Wei-Han Chene97d3532016-03-31 19:22:01 +0800234 logging.exception('wipe_in_place failed')
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800235 _OnError(station_ip, station_port, wipe_finish_token, state_dev,
236 wipe_in_tmpfs_log=logfile, wipe_init_log=None)
Wei-Han Chene97d3532016-03-31 19:22:01 +0800237 raise
238
239
240def _StopAllUpstartJobs(exclude_list=None):
241 logging.debug('stopping upstart jobs')
242
243 # Try three times to stop running services because some service will respawn
244 # one time after being stopped, e.g. shill_respawn. Two times should be enough
245 # to stop shill. Adding one more try for safety.
246
247 if exclude_list is None:
248 exclude_list = []
249
250 for unused_tries in xrange(3):
251 service_list = process_utils.SpawnOutput(['initctl', 'list']).splitlines()
252 service_list = [
253 line.split()[0] for line in service_list if 'start/running' in line]
254 for service in service_list:
Wei-Han Chenc8f24562016-04-23 19:42:42 +0800255 if service in exclude_list or service.startswith('console-'):
Wei-Han Chene97d3532016-03-31 19:22:01 +0800256 continue
Wei-Han Chenc8f24562016-04-23 19:42:42 +0800257 process_utils.Spawn(['stop', service], call=True, log=True)
Wei-Han Chene97d3532016-03-31 19:22:01 +0800258
259
Wei-Han Chenc8f24562016-04-23 19:42:42 +0800260def _UnmountStatefulPartition(root, state_dev):
Wei-Han Chene97d3532016-03-31 19:22:01 +0800261 logging.debug('unmount stateful partition')
Wei-Han Chene97d3532016-03-31 19:22:01 +0800262 # mount points that need chromeos_shutdown to umount
263
264 # 1. find mount points on stateful partition
Wei-Han Chenc8f24562016-04-23 19:42:42 +0800265 mount_output = process_utils.SpawnOutput(['mount'], log=True)
Wei-Han Chene97d3532016-03-31 19:22:01 +0800266
Wei-Han Chenc8f24562016-04-23 19:42:42 +0800267 mount_point_list = []
268 for line in mount_output.splitlines():
269 fields = line.split()
270 if fields[0] == state_dev:
271 mount_point_list.append(fields[2])
272
273 logging.debug('stateful partitions mounted on: %s', mount_point_list)
Wei-Han Chene97d3532016-03-31 19:22:01 +0800274 # 2. find processes that are using stateful partitions
275
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800276 def _ListProcOpening(path_list):
277 lsof_cmd = ['lsof', '-t'] + path_list
Wei-Han Chene97d3532016-03-31 19:22:01 +0800278 return [int(line)
279 for line in process_utils.SpawnOutput(lsof_cmd).splitlines()]
280
Hung-Te Lin09226ef2017-01-11 18:00:19 +0800281 def _ListMinijail():
282 # Not sure why, but if we use 'minijail0', then we can't find processes that
283 # starts with /sbin/minijail0.
284 list_cmd = ['pgrep', 'minijail']
285 return [int(line)
286 for line in process_utils.SpawnOutput(list_cmd).splitlines()]
287
Wei-Han Chene97d3532016-03-31 19:22:01 +0800288 proc_list = _ListProcOpening(mount_point_list)
289
Wei-Han Chenc8f24562016-04-23 19:42:42 +0800290 if os.getpid() in proc_list:
Wei-Han Chene97d3532016-03-31 19:22:01 +0800291 logging.error('wipe_init itself is using stateful partition')
292 logging.error(
293 'lsof: %s',
294 process_utils.SpawnOutput('lsof -p %d' % os.getpid(), shell=True))
295 raise RuntimeError('using stateful partition')
296
297 def _KillOpeningBySignal(sig):
298 proc_list = _ListProcOpening(mount_point_list)
299 if not proc_list:
300 return True # we are done
301 for pid in proc_list:
Wei-Han Chenc8f24562016-04-23 19:42:42 +0800302 try:
303 os.kill(pid, sig)
Hung-Te Linc8174b52017-06-02 11:11:45 +0800304 except Exception:
Wei-Han Chenc8f24562016-04-23 19:42:42 +0800305 logging.exception('killing process %d failed', pid)
Wei-Han Chene97d3532016-03-31 19:22:01 +0800306 return False # need to check again
307
308 sync_utils.Retry(10, 0.1, None, _KillOpeningBySignal, signal.SIGTERM)
309 sync_utils.Retry(10, 0.1, None, _KillOpeningBySignal, signal.SIGKILL)
310
311 proc_list = _ListProcOpening(mount_point_list)
312 assert not proc_list, "processes using stateful partition: %s" % proc_list
313
You-Cheng Syu2ea26dd2016-12-06 20:50:05 +0800314 def _Unmount(mount_point, critical):
Hung-Te Lin09226ef2017-01-11 18:00:19 +0800315 logging.info('try to unmount %s', mount_point)
You-Cheng Syu2ea26dd2016-12-06 20:50:05 +0800316 for unused_i in xrange(10):
317 output = process_utils.Spawn(['umount', '-n', '-R', mount_point],
318 read_stderr=True, log=True).stderr_data
319 # some mount points need to be unmounted multiple times.
320 if (output.endswith(': not mounted\n') or
321 output.endswith(': not found\n')):
322 return
323 time.sleep(0.5)
Hung-Te Lin09226ef2017-01-11 18:00:19 +0800324 logging.error('failed to unmount %s', mount_point)
You-Cheng Syu2ea26dd2016-12-06 20:50:05 +0800325 if critical:
326 raise RuntimeError('Unmounting %s is critical. Stop.')
327
Wei-Han Chene97d3532016-03-31 19:22:01 +0800328 if os.path.exists(os.path.join(root, 'dev', 'mapper', 'encstateful')):
Hung-Te Lin09226ef2017-01-11 18:00:19 +0800329
330 # minijail will make encstateful busy, but usually we can't just kill them.
331 # Need to list the processes and solve each-by-each.
332 proc_list = _ListMinijail()
333 assert not proc_list, "processes still using minijail: %s" % proc_list
334
You-Cheng Syuf0990462016-09-07 14:56:19 +0800335 # Doing what 'mount-encrypted umount' should do.
336 for mount_point in mount_point_list:
You-Cheng Syu2ea26dd2016-12-06 20:50:05 +0800337 _Unmount(mount_point, False)
338 _Unmount(os.path.join(root, 'var'), True)
Jeffy Chend5b08e12017-03-06 10:22:59 +0800339 process_utils.Spawn(['dmsetup', 'remove', 'encstateful',
340 '--noudevrules', '--noudevsync'], check_call=True)
You-Cheng Syuf0990462016-09-07 14:56:19 +0800341 process_utils.Spawn(['losetup', '-D'], check_call=True)
Wei-Han Chene97d3532016-03-31 19:22:01 +0800342
343 for mount_point in mount_point_list:
You-Cheng Syu2ea26dd2016-12-06 20:50:05 +0800344 _Unmount(mount_point, True)
Wei-Han Chene97d3532016-03-31 19:22:01 +0800345 process_utils.Spawn(['sync'], call=True)
346
You-Cheng Syuf0990462016-09-07 14:56:19 +0800347 # Check if the stateful partition is unmounted successfully.
348 process_utils.Spawn(r'mount | grep -c "^\S*stateful" | grep -q ^0$',
349 shell=True, check_call=True)
350
Wei-Han Chene97d3532016-03-31 19:22:01 +0800351
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800352def _InformStation(ip, port, token, wipe_init_log=None,
353 wipe_in_tmpfs_log=None, success=True):
354 if not ip:
355 return
356 port = int(port)
357
358 logging.debug('inform station %s:%d', ip, port)
359
360 try:
361 sync_utils.WaitFor(
362 lambda: 0 == process_utils.Spawn(['ping', '-w1', '-c1', ip],
363 call=True).returncode,
364 timeout_secs=180, poll_interval=1)
Hung-Te Linc8174b52017-06-02 11:11:45 +0800365 except Exception:
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800366 logging.exception('cannot get network connection...')
367 else:
368 sock = socket.socket()
369 sock.connect((ip, port))
370
371 response = dict(token=token, success=success)
372
373 if wipe_init_log:
374 with open(wipe_init_log) as f:
375 response['wipe_init_log'] = f.read()
376
377 if wipe_in_tmpfs_log:
378 with open(wipe_in_tmpfs_log) as f:
379 response['wipe_in_tmpfs_log'] = f.read()
380
381 sock.sendall(json.dumps(response) + '\n')
382 sock.close()
383
384
385def _WipeStateDev(release_rootfs, root_disk, wipe_args):
Wei-Han Chen9adf9de2016-04-01 19:35:41 +0800386 stateful_partition_path = '/mnt/stateful_partition'
387
Wei-Han Chen9adf9de2016-04-01 19:35:41 +0800388 clobber_state_env = os.environ.copy()
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800389 clobber_state_env.update(ROOT_DEV=release_rootfs,
Earl Oueeb289d2016-11-04 14:36:40 +0800390 ROOT_DISK=root_disk)
Wei-Han Chen9adf9de2016-04-01 19:35:41 +0800391 logging.debug('clobber-state: root_dev=%s, root_disk=%s',
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800392 release_rootfs, root_disk)
Wei-Han Chen9adf9de2016-04-01 19:35:41 +0800393 process_utils.Spawn(['clobber-state', wipe_args], env=clobber_state_env,
394 call=True)
Wei-Han Chen9adf9de2016-04-01 19:35:41 +0800395 # remove developer flag, which is created by clobber-state after wiping.
396 try:
Wei-Han Chene5b19f42016-10-21 14:45:10 +0800397 os.unlink(os.path.join(stateful_partition_path, '.developer_mode'))
Wei-Han Chen9adf9de2016-04-01 19:35:41 +0800398 except OSError:
399 pass
Wei-Han Chene5b19f42016-10-21 14:45:10 +0800400 # make sure that everything is synced
401 for unused_i in xrange(3):
402 process_utils.Spawn(['sync'], call=True)
403 time.sleep(1)
Wei-Han Chen9adf9de2016-04-01 19:35:41 +0800404
Joel Kitching679a00b2016-08-03 11:42:58 +0800405
Earl Ou564a7872016-10-05 10:22:00 +0800406def EnableReleasePartition(release_rootfs):
407 """Enables a release image partition on disk."""
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800408 logging.debug('enable release partition: %s', release_rootfs)
409 Util().EnableReleasePartition(release_rootfs)
Earl Ou564a7872016-10-05 10:22:00 +0800410 logging.debug('Device will boot from %s after reboot.', release_rootfs)
Wei-Han Chen9adf9de2016-04-01 19:35:41 +0800411
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800412
413def _InformShopfloor(shopfloor_url):
Wei-Han Chen9adf9de2016-04-01 19:35:41 +0800414 if shopfloor_url:
415 logging.debug('inform shopfloor %s', shopfloor_url)
Hung-Te Lina3195462016-10-14 15:48:29 +0800416 proc = process_utils.Spawn(
417 [os.path.join(CUTOFF_SCRIPT_DIR, 'inform_shopfloor.sh'), shopfloor_url,
418 'factory_wipe'], check_call=True)
Wei-Han Chen9adf9de2016-04-01 19:35:41 +0800419 logging.debug('stdout: %s', proc.stdout_data)
420 logging.debug('stderr: %s', proc.stderr_data)
421
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800422
Hung-Te Lin7b27f0c2016-10-18 18:41:29 +0800423def _Cutoff():
424 logging.debug('cutoff')
Hung-Te Lina3195462016-10-14 15:48:29 +0800425 cutoff_script = os.path.join(CUTOFF_SCRIPT_DIR, 'cutoff.sh')
Hung-Te Lin7b27f0c2016-10-18 18:41:29 +0800426 process_utils.Spawn('%s' % (cutoff_script), shell=True, check_call=True)
Wei-Han Chen9adf9de2016-04-01 19:35:41 +0800427
428
Hung-Te Lin7b27f0c2016-10-18 18:41:29 +0800429def WipeInit(wipe_args, shopfloor_url, state_dev, release_rootfs,
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800430 root_disk, old_root, station_ip, station_port, finish_token):
Wei-Han Chenc8f24562016-04-23 19:42:42 +0800431 Daemonize()
Wei-Han Chene97d3532016-03-31 19:22:01 +0800432 logfile = '/tmp/wipe_init.log'
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800433 wipe_in_tmpfs_log = os.path.join(old_root, 'tmp', WIPE_IN_TMPFS_LOG)
Wei-Han Chene97d3532016-03-31 19:22:01 +0800434 ResetLog(logfile)
435
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800436 logging.debug('wipe_args: %s', wipe_args)
Wei-Han Chen0a3320e2016-04-23 01:32:07 +0800437 logging.debug('shopfloor_url: %s', shopfloor_url)
438 logging.debug('state_dev: %s', state_dev)
439 logging.debug('release_rootfs: %s', release_rootfs)
440 logging.debug('root_disk: %s', root_disk)
441 logging.debug('old_root: %s', old_root)
Wei-Han Chene97d3532016-03-31 19:22:01 +0800442
Wei-Han Chene97d3532016-03-31 19:22:01 +0800443 try:
Shun-Hsing Oub5724832016-07-21 11:45:58 +0800444 _StopAllUpstartJobs(exclude_list=[
445 # Milestone marker that use to determine the running of other services.
446 'boot-services',
447 'system-services',
448 'failsafe',
449 # Keep dbus to make sure we can shutdown the device.
450 'dbus',
451 # Keep shill for connecting to shopfloor or stations.
452 'shill',
453 # Keep openssh-server for debugging purpose.
454 'openssh-server',
455 # sslh is a service in ARC++ for muxing between ssh and adb.
456 'sslh'
457 ])
Wei-Han Chenc8f24562016-04-23 19:42:42 +0800458 _UnmountStatefulPartition(old_root, state_dev)
Wei-Han Chen9adf9de2016-04-01 19:35:41 +0800459
Hung-Te Lina3195462016-10-14 15:48:29 +0800460 process_utils.Spawn(
461 [os.path.join(CUTOFF_SCRIPT_DIR, 'display_wipe_message.sh'), 'wipe'],
462 call=True)
Wei-Han Chen9adf9de2016-04-01 19:35:41 +0800463
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800464 _WipeStateDev(release_rootfs, root_disk, wipe_args)
465
Earl Ou564a7872016-10-05 10:22:00 +0800466 EnableReleasePartition(release_rootfs)
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800467
468 _InformShopfloor(shopfloor_url)
469
470 _InformStation(station_ip, station_port, finish_token,
471 wipe_init_log=logfile,
472 wipe_in_tmpfs_log=wipe_in_tmpfs_log,
473 success=True)
474
Hung-Te Lin7b27f0c2016-10-18 18:41:29 +0800475 _Cutoff()
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800476
477 # should not reach here
478 time.sleep(1e8)
Hung-Te Linc8174b52017-06-02 11:11:45 +0800479 except Exception:
Wei-Han Chene97d3532016-03-31 19:22:01 +0800480 logging.exception('wipe_init failed')
Wei-Han Chenbe1355a2016-04-24 19:31:03 +0800481 _OnError(station_ip, station_port, finish_token, state_dev,
482 wipe_in_tmpfs_log=wipe_in_tmpfs_log, wipe_init_log=logfile)
Wei-Han Chene97d3532016-03-31 19:22:01 +0800483 raise