ronnie
2022-10-14 1504bb53e29d3d46222c0b3ea994fc494b48e153
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
 
import errno
import logging
import os
import shutil
import subprocess
import urllib2
 
from autotest_lib.client.common_lib import global_config
 
def rm_dir_if_exists(dir_to_remove):
    """
    Removes a directory. Does not fail if the directory does NOT exist.
 
    @param dir_to_remove: path, directory to be removed.
 
    """
    try:
        shutil.rmtree(dir_to_remove)
    except OSError as e:
        if e.errno != errno.ENOENT:
            raise
 
 
def rm_dirs_if_exist(dirs_to_remove):
    """
    Removes multiple directories. Does not fail if directories do NOT exist.
 
    @param dirs_to_remove: list of directory paths to be removed.
 
    """
    for dr in dirs_to_remove:
        rm_dir_if_exists(dr)
 
 
def ensure_file_exists(filepath):
    """
    Verifies path given points to an existing file.
 
    @param filepath: path, path to check.
 
    @raises IOError if the path given does not point to a valid file.
 
    """
    error_msg = 'File %s does not exist.' % filepath
    if not os.path.isfile(filepath):
        raise IOError(error_msg)
 
 
def ensure_all_files_exist(filepaths):
    """
    Verifies all paths given point to existing files.
 
    @param filepaths: List of paths to check.
 
    @raises IOError if given paths do not point to existing files.
 
    """
    for filepath in filepaths:
        ensure_file_exists(filepath)
 
 
def ensure_dir_exists(dirpath):
    """
    Verifies path given points to an existing directory.
 
    @param dirpath: path, dir to check.
 
    @raises IOError if path does not point to an existing directory.
 
    """
    error_msg = 'Directory %s does not exist.' % dirpath
    if not os.path.isdir(dirpath):
        raise IOError(error_msg)
 
 
def ensure_all_dirs_exist(dirpaths):
    """
    Verifies all paths given point to existing directories.
 
    @param dirpaths: list of directory paths to check.
 
    @raises IOError if given paths do not point to existing directories.
 
    """
    for dirpath in dirpaths:
        ensure_dir_exists(dirpath)
 
 
def make_leaf_dir(dirpath):
    """
    Creates a directory, also creating parent directories if they do not exist.
 
    @param dirpath: path, directory to create.
 
    @raises whatever exception raised other than "path already exist".
 
    """
    try:
        os.makedirs(dirpath)
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise
 
 
def make_leaf_dirs(dirpaths):
    """
    Creates multiple directories building all respective parent directories if
    they do not exist.
 
    @param dirpaths: list of directory paths to create.
 
    @raises whatever exception raised other than "path already exists".
    """
    for dirpath in dirpaths:
        make_leaf_dir(dirpath)
 
 
def download_file(remote_path, local_path):
    """
    Download file from a remote resource.
 
    @param remote_path: path, complete path to the remote file.
    @param local_path: path, complete path to save downloaded file.
 
    @raises: urllib2.HTTPError or urlib2.URLError exception. Both with added
            debug information
 
    """
    client_config = global_config.global_config.get_section_values('CLIENT')
    proxies = {}
 
    for name, value in client_config.items('CLIENT'):
        if value and name.endswith('_proxy'):
            proxies[name[:-6]] = value
 
    if proxies:
        proxy_handler = urllib2.ProxyHandler(proxies)
        opener = urllib2.build_opener(proxy_handler)
        urllib2.install_opener(opener)
 
    # Unlike urllib.urlopen urllib2.urlopen will immediately throw on error
    # If we could not find the file pointed by remote_path we will get an
    # exception, catch the exception to log useful information then re-raise
 
    try:
        remote_file = urllib2.urlopen(remote_path)
 
        # Catch exceptions, extract exception properties and then re-raise
        # This helps us with debugging what went wrong quickly as we get to see
        # test_that output immediately
 
    except urllib2.HTTPError as e:
        e.msg = (("""HTTPError raised while retrieving file %s\n.
                       Http Code = %s.\n. Reason = %s\n. Headers = %s.\n
                       Original Message = %s.\n""")
                 % (remote_path, e.code, e.reason, e.headers, e.msg))
        raise
 
    except urllib2.URLError as e:
        e.msg = (("""URLError raised while retrieving file %s\n.
                        Reason = %s\n. Original Message = %s\n.""")
                 % (remote_path, e.reason, e.message))
        raise
 
    with open(local_path, 'wb') as local_file:
        while True:
            block = remote_file.read(128 * 1024)
            if not block:
                break
            local_file.write(block)
 
 
def get_directory_size_kibibytes(directory):
    """Calculate the total size of a directory with all its contents.
 
    @param directory: Path to the directory
 
    @return Size of the directory in kibibytes.
    """
    cmd = ['du', '-sk', directory]
    process = subprocess.Popen(cmd,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
    stdout_data, stderr_data = process.communicate()
 
    if process.returncode != 0:
        # This function is used for statistics only, if it fails,
        # nothing else should crash.
        logging.warning('Getting size of %s failed. Stderr:', directory)
        logging.warning(stderr_data)
        return 0
 
    return int(stdout_data.split('\t', 1)[0])
 
 
def recursive_path_permission(path):
    """
    Recursively lists a path and its parent's permission.
 
    For a path, it emits a path_perm string "<path> <permission>" where
    <permission> is an octal representation of the path's st_mode. After that,
    it emits its parent's path_perm string(s) recursively.
    For example, recursive_path_permission('/foo/bar/buz') returns
    ['/foo/bar/buz 0100644', '/foo/bar 040755', '/foo 040755', '/ 040755']
 
    If |path| is invalid, it returns empty list.
    If |path| does not have parent directory, it returns a list with only its
    own path_perm string.
 
    @param path: file path.
 
    @return list of "<path> <permission>" string.
    """
    def path_st_mode(p):
        """
        Gets path's permission.
 
        @param p: file path.
 
        @return "<path> <permission>" where <permission> is an octal
        representation of the path's st_mode.
        """
        return '%s %s' % (p, oct(os.stat(p).st_mode))
 
    if not path or not os.path.exists(path):
        return []
    if path == '/':
        return [path_st_mode(path)]
    dirname, basename = os.path.split(path)
    if not basename:
        return recursive_path_permission(dirname)
    result = [path_st_mode(path)]
    if dirname:
        result.extend(recursive_path_permission(dirname))
    return result