Merge "[GENERAL] Add Andreas Geissler as committer."
[oom/offline-installer.git] / build / download / rpm_downloader.py
1 #! /usr/bin/env python3
2 # -*- coding: utf-8 -*-
3
4 #   COPYRIGHT NOTICE STARTS HERE
5
6 #   Copyright 2019 © Samsung Electronics Co., Ltd.
7 #
8 #   Licensed under the Apache License, Version 2.0 (the "License");
9 #   you may not use this file except in compliance with the License.
10 #   You may obtain a copy of the License at
11 #
12 #       http://www.apache.org/licenses/LICENSE-2.0
13 #
14 #   Unless required by applicable law or agreed to in writing, software
15 #   distributed under the License is distributed on an "AS IS" BASIS,
16 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 #   See the License for the specific language governing permissions and
18 #   limitations under the License.
19
20 #   COPYRIGHT NOTICE ENDS HERE
21
22 import argparse
23 import datetime
24 import logging
25 import os
26 import subprocess
27 import sys
28 import timeit
29 from collections import defaultdict
30
31 from command_downloader import CommandDownloader
32
33 log = logging.getLogger(name=__name__)
34
35
36 class RpmDownloader(CommandDownloader):
37     def __init__(self, *list_args):
38         super().__init__('rpm packages', 'yumdownloader', *list_args)
39         # beneficial to have it in same format
40
41     @property
42     def check_table(self):
43         """
44         Return check table for rpm packages
45         :return: '' not implemented
46         """
47         log.warning('Check mode for rpms is not implemented.')
48         return ''
49
50     @staticmethod
51     def _download_rpm_set(dst, rpms):
52         command = 'yumdownloader --destdir={} {}'.format(dst, ' '.join(rpms))
53         log.info('Running command: {}'.format(command))
54         log.info(
55             subprocess.check_output(command.split(), stderr=subprocess.STDOUT).decode())
56         log.info('Downloaded: {}'.format(', '.join(sorted(rpms))))
57
58     def missing(self):
59         """
60         Check for missing rpms (not downloaded)
61         :return: dictionary of missing items grouped by dst dir
62         """
63         # we need slightly different format for yumdownloader
64         self._missing = defaultdict(set)
65         for item, dst in self._data_list.items():
66             self._missing[dst].add(item)
67         return self._missing
68
69     def _is_missing(self, item): # pylint: disable=W0613
70         """
71         Check if item is missing
72         :param item: item to check
73         :return: it is always missing because not sure about downloaded filename
74         """
75         # don't know file names so always missing
76         return True
77
78     def _initial_log(self):
79         """
80         Simpler then in parent
81         """
82         class_name = type(self).__name__
83         log.info('{}: Initializing download {} {} are not present.'.format(class_name, len(self._data_list),
84                                                                            self._list_type))
85
86     def download(self):
87         """
88         Download rpm packages from lists
89         """
90         self._initial_log()
91         error_occurred = False
92
93         for dst, rpm_set in self._missing.items():
94             try:
95                 self._download_rpm_set(dst, rpm_set)
96             except subprocess.CalledProcessError as err:
97                 log.exception(err.output)
98                 error_occurred = True
99         if error_occurred:
100             log.error('Download failed')
101             raise RuntimeError('Download unsuccessful')
102
103
104 def run_cli():
105     """
106     Run as cli tool
107     """
108     parser = argparse.ArgumentParser(description='Download rpm packages from list')
109     parser.add_argument('rpm_list', metavar='rpm-list',
110                         help='File with list of npm packages to download.')
111     parser.add_argument('--output-dir', '-o', default=os.getcwd(),
112                         help='Download destination')
113
114     args = parser.parse_args()
115
116     logging.basicConfig(stream=sys.stdout, level=logging.INFO, format='%(message)s')
117
118     timer_start = timeit.default_timer()
119     try:
120         downloader = RpmDownloader([args.rpm_list, args.output_dir])
121         downloader.download()
122     except RuntimeError:
123         sys.exit(1)
124     finally:
125         log.info('Downloading finished in {}'.format(
126             datetime.timedelta(seconds=timeit.default_timer() - timer_start)))
127
128
129 if __name__ == '__main__':
130     run_cli()