blob: c911def16b9b0a93e7fd26652839fa55803d217d [file] [log] [blame]
xixuan52c2fba2016-05-20 17:02:48 -07001# Copyright (c) 2016 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""A progress class for tracking CrOS auto-update process.
6
7This class is mainly designed for:
8 1. Set the pattern for generating the filenames of
9 track_status_file/execute_log_file.
10 track_status_file: Used for record the current step of CrOS auto-update
11 process. Only has one line.
12 execute_log_file: Used for record the whole logging info of the CrOS
13 auto-update process, including any debug information.
14 2. Write current auto-update process into the track_status_file.
15 3. Read current auto-update process from the track_status_file.
16
17This file also offers external functions that are related to add/check/delete
18the progress of the CrOS auto-update process.
19"""
20
21from __future__ import print_function
22
23import logging
24import os
25
xixuancf58dd32016-08-24 13:57:06 -070026# only import setup_chromite before chromite import.
27import setup_chromite # pylint: disable=unused-import
xixuan52c2fba2016-05-20 17:02:48 -070028try:
29 from chromite.lib import osutils
30except ImportError as e:
31 logging.debug('chromite cannot be imported: %r', e)
32 osutils = None
33
34# Path for status tracking log.
35TRACK_LOG_FILE_PATH = '/tmp/auto-update/tracking_log/%s_%s.log'
36
37# Path for executing log.
38EXECUTE_LOG_FILE_PATH = '/tmp/auto-update/executing_log/%s_%s.log'
39
40# The string for update process finished
41FINISHED = 'Completed'
42ERROR_TAG = 'Error'
43
44
45def ReadOneLine(filename):
46 """Read one line from file.
47
48 Args:
49 filename: The file to be read.
50 """
51 return open(filename, 'r').readline().rstrip('\n')
52
53
54def IsProcessAlive(pid):
55 """Detect whether a process is alive or not.
56
57 Args:
58 pid: The process id.
59 """
60 path = '/proc/%s/stat' % pid
61 try:
62 stat = ReadOneLine(path)
63 except IOError:
64 if not os.path.exists(path):
65 return False
66
67 raise
68
69 return stat.split()[2] != 'Z'
70
71
72def GetExecuteLogFile(host_name, pid):
73 """Return the whole path of execute log file."""
74 if not os.path.exists(os.path.dirname(EXECUTE_LOG_FILE_PATH)):
75 osutils.SafeMakedirs(os.path.dirname(EXECUTE_LOG_FILE_PATH))
76
77 return EXECUTE_LOG_FILE_PATH % (host_name, pid)
78
79
80def GetTrackStatusFile(host_name, pid):
81 """Return the whole path of track status file."""
82 if not os.path.exists(os.path.dirname(TRACK_LOG_FILE_PATH)):
83 osutils.SafeMakedirs(os.path.dirname(TRACK_LOG_FILE_PATH))
84
85 return TRACK_LOG_FILE_PATH % (host_name, pid)
86
87
88def DelTrackStatusFile(host_name, pid):
89 """Delete the track status log."""
90 osutils.SafeUnlink(GetTrackStatusFile(host_name, pid))
91
92
93class AUProgress(object):
94 """Used for tracking the CrOS auto-update progress."""
95
96 def __init__(self, host_name, pid):
97 """Initialize a CrOS update progress instance.
98
99 Args:
100 host_name: The name of host, should be in the file_name of the status
101 tracking file of auto-update process.
102 pid: The process id, should be in the file_name too.
103 """
104 self.host_name = host_name
105 self.pid = pid
106
107 @property
108 def track_status_file(self):
109 """The track status file to record the CrOS auto-update progress."""
110 return GetTrackStatusFile(self.host_name, self.pid)
111
112 def WriteStatus(self, content):
113 """Write auto-update progress into status tracking file.
114
115 Args:
116 content: The content to be recorded.
117 """
118 if not self.track_status_file:
119 return
120
121 try:
122 with open(self.track_status_file, 'w') as out_log:
123 out_log.write(content)
124 except Exception as e:
125 logging.error('Cannot write au status: %r', e)
126
127 def ReadStatus(self):
128 """Read auto-update progress from status tracking file."""
129 return ReadOneLine(self.track_status_file)