Yilin Yang | 19da693 | 2019-12-10 13:39:28 +0800 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 2 | # |
| 3 | # Copyright 2016 The Chromium OS Authors. All rights reserved. |
| 4 | # Use of this source code is governed by a BSD-style license that can be |
| 5 | # found in the LICENSE file. |
| 6 | |
| 7 | from __future__ import print_function |
| 8 | |
| 9 | import argparse |
chuntsen | f2e3ebd | 2019-10-28 16:49:57 +0800 | [diff] [blame] | 10 | import json |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 11 | import logging |
| 12 | import os |
| 13 | import signal |
| 14 | import sys |
chuntsen | 4cf110a | 2018-02-13 18:35:20 +0800 | [diff] [blame] | 15 | import tarfile |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 16 | |
Wei-Han Chen | d665b00 | 2019-10-03 16:16:09 +0800 | [diff] [blame] | 17 | from cros.factory.instalog import core |
| 18 | from cros.factory.instalog import daemon_utils |
Wei-Han Chen | 12edbb2 | 2019-10-03 16:40:00 +0800 | [diff] [blame] | 19 | from cros.factory.instalog import instalog_common |
Wei-Han Chen | d665b00 | 2019-10-03 16:16:09 +0800 | [diff] [blame] | 20 | from cros.factory.instalog import log_utils |
| 21 | from cros.factory.instalog.utils import file_utils |
| 22 | from cros.factory.instalog.utils import sync_utils |
| 23 | from cros.factory.instalog.utils import type_utils |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 24 | |
Wei-Han Chen | d665b00 | 2019-10-03 16:16:09 +0800 | [diff] [blame] | 25 | from cros.factory.instalog.external import jsonrpclib |
| 26 | from cros.factory.instalog.external import yaml |
Joel Kitching | 3a5e76c | 2016-12-21 13:22:22 +0800 | [diff] [blame] | 27 | |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 28 | |
Joel Kitching | 860649d | 2016-11-21 14:53:02 +0800 | [diff] [blame] | 29 | # The default number of seconds to wait before giving up on a flush. |
chuntsen | dc33ae8 | 2017-01-17 15:22:16 +0800 | [diff] [blame] | 30 | _DEFAULT_FLUSH_TIMEOUT = 30 |
| 31 | _DEFAULT_STOP_TIMEOUT = 10 |
Joel Kitching | 860649d | 2016-11-21 14:53:02 +0800 | [diff] [blame] | 32 | |
| 33 | |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 34 | class InstalogService(daemon_utils.Daemon): |
| 35 | """Represents the Instalog daemon service.""" |
| 36 | |
| 37 | def __init__(self, config, logging_level): |
| 38 | self._config = config |
| 39 | self._logging_level = logging_level |
| 40 | self._core = None |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 41 | super(InstalogService, self).__init__( |
| 42 | pidfile=config['instalog']['pid_file']) |
| 43 | |
| 44 | def _SignalHandler(self, signal_num, frame): |
Joel Kitching | 8e514ce | 2017-03-29 14:04:33 +0800 | [diff] [blame] | 45 | """Signal handler to stop Instalog on SIGINT or SIGTERM.""" |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 46 | del frame |
Joel Kitching | 8e514ce | 2017-03-29 14:04:33 +0800 | [diff] [blame] | 47 | logging.debug('_SignalHandler called with signalnum=%s', signal_num) |
| 48 | if signal_num not in [signal.SIGINT, signal.SIGTERM]: |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 49 | return |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 50 | if self._core: |
Joel Kitching | 8e514ce | 2017-03-29 14:04:33 +0800 | [diff] [blame] | 51 | # No need for a lock since _SignalHandler will only ever be called from |
| 52 | # Instalog's main thread. |
| 53 | signal_string = 'SIGINT' if signal_num == signal.SIGINT else 'SIGTERM' |
| 54 | logging.warning('%s detected, stopping', signal_string) |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 55 | self._core.Stop() |
| 56 | self._core = None |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 57 | |
chuntsen | c8e2a57 | 2018-01-11 19:30:40 +0800 | [diff] [blame] | 58 | def _InitLogging(self, foreground): |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 59 | """Sets up logging.""" |
chuntsen | c8e2a57 | 2018-01-11 19:30:40 +0800 | [diff] [blame] | 60 | handlers = [] |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 61 | |
| 62 | # Save logging calls to log file. |
Peter Shih | b4e4935 | 2017-05-25 17:35:11 +0800 | [diff] [blame] | 63 | log_file = self._config['instalog']['log_file'] |
| 64 | file_utils.TryMakeDirs(os.path.dirname(log_file)) |
chuntsen | c8e2a57 | 2018-01-11 19:30:40 +0800 | [diff] [blame] | 65 | handlers.append(log_utils.GetFileHandler(log_file, self._logging_level)) |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 66 | |
chuntsen | c8e2a57 | 2018-01-11 19:30:40 +0800 | [diff] [blame] | 67 | # Output logging calls to console when foreground is set. |
| 68 | if foreground: |
| 69 | handlers.append(log_utils.GetStreamHandler(self._logging_level)) |
| 70 | |
| 71 | log_utils.InitLogging(handlers) |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 72 | |
Chun-Tsen Kuo | a874f78 | 2018-03-26 14:26:13 +0800 | [diff] [blame] | 73 | def Run(self, foreground, rpc_ready=None): |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 74 | """Starts Instalog.""" |
chuntsen | c8e2a57 | 2018-01-11 19:30:40 +0800 | [diff] [blame] | 75 | self._InitLogging(foreground) |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 76 | |
Joel Kitching | 8e514ce | 2017-03-29 14:04:33 +0800 | [diff] [blame] | 77 | signal.signal(signal.SIGINT, self._SignalHandler) |
| 78 | signal.signal(signal.SIGTERM, self._SignalHandler) |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 79 | |
| 80 | self._core = core.Instalog( |
| 81 | node_id=self._config['instalog']['node_id'], |
Joel Kitching | 9edac3b | 2016-10-23 10:40:24 +0700 | [diff] [blame] | 82 | data_dir=self._config['instalog']['data_dir'], |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 83 | cli_hostname=self._config['instalog']['cli_hostname'], |
| 84 | cli_port=self._config['instalog']['cli_port'], |
| 85 | buffer_plugin=self._config['buffer'], |
| 86 | input_plugins=self._config['input'], |
| 87 | output_plugins=self._config['output']) |
Chun-Tsen Kuo | a874f78 | 2018-03-26 14:26:13 +0800 | [diff] [blame] | 88 | # After the core initialized, the RPC server is ready. |
| 89 | if rpc_ready: |
| 90 | rpc_ready.set() |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 91 | self._core.Run() |
| 92 | |
| 93 | |
Fei Shao | bd07c9a | 2020-06-15 19:04:50 +0800 | [diff] [blame^] | 94 | class InstalogCLI: |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 95 | """Represents the CLI interface used to control Instalog.""" |
| 96 | |
| 97 | def __init__(self, args): |
| 98 | # Read config file. |
| 99 | config_path = self._LocateConfigFile(args.config) |
| 100 | if config_path is None: |
| 101 | exit('No config file found') |
| 102 | with open(config_path) as f: |
| 103 | config = yaml.load(f) |
chuntsen | 4cf110a | 2018-02-13 18:35:20 +0800 | [diff] [blame] | 104 | self._CheckDataDir(config) |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 105 | |
| 106 | # logging.WARNING = 30, logging.INFO = 20, logging.DEBUG = 10 |
| 107 | logging_level = logging.INFO - ((args.verbose - args.quiet) * 10) |
| 108 | |
| 109 | self._service = InstalogService(config, logging_level) |
| 110 | self._core = jsonrpclib.Server( |
| 111 | 'http://%s:%s' % (config['instalog']['cli_hostname'], |
| 112 | config['instalog']['cli_port'])) |
| 113 | |
| 114 | if args.cmd == 'start': |
| 115 | self.Start(args.foreground) |
| 116 | elif args.cmd == 'stop': |
chuntsen | dc33ae8 | 2017-01-17 15:22:16 +0800 | [diff] [blame] | 117 | self.Stop(args.timeout) |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 118 | elif args.cmd == 'restart': |
| 119 | self.Restart() |
| 120 | elif args.cmd == 'status': |
| 121 | self.Status() |
Joel Kitching | 2329397 | 2016-11-18 17:24:47 +0800 | [diff] [blame] | 122 | elif args.cmd == 'inspect': |
| 123 | self.Inspect(args.plugin_id, args.json_path) |
Joel Kitching | 860649d | 2016-11-21 14:53:02 +0800 | [diff] [blame] | 124 | elif args.cmd == 'flush': |
| 125 | self.Flush(args.plugin_id, args.timeout) |
chuntsen | 4cf110a | 2018-02-13 18:35:20 +0800 | [diff] [blame] | 126 | elif args.cmd == 'archive': |
chuntsen | aabb242 | 2018-03-07 16:16:09 +0800 | [diff] [blame] | 127 | self.Archive(config_path, config['instalog']['data_dir'], |
chuntsen | 4cf110a | 2018-02-13 18:35:20 +0800 | [diff] [blame] | 128 | args.archive_path, args.details) |
chuntsen | 65e9f38 | 2018-07-09 18:24:32 +0800 | [diff] [blame] | 129 | elif args.cmd == 'progress': |
| 130 | self.Progress(args.plugin_id, args.details) |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 131 | |
| 132 | def _LocateConfigFile(self, user_path): |
| 133 | """Locates the config file that should be used by Instalog.""" |
| 134 | if user_path: |
| 135 | return user_path |
| 136 | paths = [ |
| 137 | os.path.join(os.getcwd(), 'instalog.yaml'), |
| 138 | os.path.join(os.path.dirname(os.path.realpath(__file__)), |
| 139 | 'instalog.yaml'), |
| 140 | os.path.join(os.path.expanduser('~'), '.instalog.yaml'), |
Joel Kitching | 24e0124 | 2016-11-25 15:17:29 +0800 | [diff] [blame] | 141 | os.path.join(os.sep, 'etc', 'instalog.yaml'), |
Hung-Te Lin | b0a32bb | 2017-01-05 15:11:06 +0800 | [diff] [blame] | 142 | os.path.join(os.sep, 'run', 'instalog.yaml')] |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 143 | for path in paths: |
| 144 | logging.debug('Checking %s for config file...', path) |
| 145 | if os.path.exists(path): |
| 146 | logging.info('Config file found at %s', path) |
| 147 | return path |
chuntsen | f2e3ebd | 2019-10-28 16:49:57 +0800 | [diff] [blame] | 148 | return None |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 149 | |
chuntsen | 4cf110a | 2018-02-13 18:35:20 +0800 | [diff] [blame] | 150 | def _CheckDataDir(self, config): |
| 151 | data_dir = config['instalog']['data_dir'] |
| 152 | if not os.path.exists(data_dir): |
| 153 | os.makedirs(data_dir) |
| 154 | instalog_dir = instalog_common.INSTALOG_DIR |
| 155 | for path, unused_dirs, unused_files in os.walk( |
| 156 | instalog_dir, followlinks=True): |
| 157 | if not os.path.islink(path) and os.path.samefile(path, data_dir): |
| 158 | print('You should not put the data_dir in the Instalog source code') |
| 159 | sys.exit(1) |
| 160 | |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 161 | def Restart(self): |
| 162 | """Restarts the daemon.""" |
chuntsen | dc33ae8 | 2017-01-17 15:22:16 +0800 | [diff] [blame] | 163 | self.Stop(_DEFAULT_STOP_TIMEOUT) |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 164 | self.Start(False) |
| 165 | |
| 166 | def Start(self, foreground): |
| 167 | """Starts the daemon. |
| 168 | |
| 169 | Args: |
| 170 | foreground: Does not detach the daemon. |
| 171 | """ |
| 172 | print('Starting...') |
Chun-Tsen Kuo | a874f78 | 2018-03-26 14:26:13 +0800 | [diff] [blame] | 173 | if not self._service.Start(foreground): |
| 174 | return |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 175 | if foreground: |
| 176 | return |
Joel Kitching | 11bbbe7 | 2016-12-07 11:43:38 +0800 | [diff] [blame] | 177 | |
| 178 | # First, wait for the daemon process to start. |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 179 | try: |
| 180 | sync_utils.WaitFor(self._service.IsRunning, 10) |
| 181 | except type_utils.TimeoutError: |
Joel Kitching | 11bbbe7 | 2016-12-07 11:43:38 +0800 | [diff] [blame] | 182 | print('Daemon could not be brought up, check the logs') |
| 183 | sys.exit(1) |
| 184 | |
| 185 | def TryIsUp(): |
| 186 | try: |
| 187 | # Perform the real check to see if Instalog is up internally. |
| 188 | return self._core.IsUp() |
| 189 | except Exception: |
| 190 | raise type_utils.TimeoutError('Could not call core IsUp') |
| 191 | |
| 192 | try: |
Chun-Tsen Kuo | a874f78 | 2018-03-26 14:26:13 +0800 | [diff] [blame] | 193 | print('Waiting for the core is up...') |
Joel Kitching | 11bbbe7 | 2016-12-07 11:43:38 +0800 | [diff] [blame] | 194 | if sync_utils.WaitFor(TryIsUp, 10): |
| 195 | print('DONE') |
| 196 | return |
| 197 | except type_utils.TimeoutError: |
| 198 | pass |
| 199 | print('Daemon could not be brought up, check the logs') |
| 200 | sys.exit(1) |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 201 | |
chuntsen | dc33ae8 | 2017-01-17 15:22:16 +0800 | [diff] [blame] | 202 | def Stop(self, timeout): |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 203 | """Stops the daemon.""" |
| 204 | # First, send the "stop" instruction to the daemon. |
| 205 | print('Stopping...') |
| 206 | try: |
| 207 | self._core.Stop() |
| 208 | except Exception: |
| 209 | print('Could not connect to daemon, is it running?') |
| 210 | sys.exit(1) |
| 211 | |
| 212 | # Then, wait for the process to come down. |
| 213 | try: |
chuntsen | dc33ae8 | 2017-01-17 15:22:16 +0800 | [diff] [blame] | 214 | sync_utils.WaitFor(self._service.IsStopped, timeout) |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 215 | except type_utils.TimeoutError: |
| 216 | print('Still shutting down?') |
| 217 | sys.exit(1) |
| 218 | else: |
| 219 | print('DONE') |
| 220 | |
| 221 | def Status(self): |
| 222 | """Prints the status of the daemon.""" |
| 223 | running = self._service.IsRunning() |
Joel Kitching | bed7d45 | 2017-04-01 00:21:08 -0700 | [diff] [blame] | 224 | if running: |
| 225 | up = self._core.IsUp() |
| 226 | print('UP' if up else 'STARTING') |
| 227 | else: |
| 228 | print('DOWN') |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 229 | |
Joel Kitching | 2329397 | 2016-11-18 17:24:47 +0800 | [diff] [blame] | 230 | def Inspect(self, plugin_id, json_path): |
| 231 | """Inspects the store of a given plugin.""" |
| 232 | success, value = self._core.Inspect(plugin_id, json_path) |
| 233 | print(value) |
| 234 | if not success: |
| 235 | sys.exit(1) |
| 236 | |
Joel Kitching | 860649d | 2016-11-21 14:53:02 +0800 | [diff] [blame] | 237 | def Flush(self, plugin_id, timeout): |
| 238 | """Flushes the given plugin with given timeout.""" |
| 239 | success, value = self._core.Flush(plugin_id, timeout) |
chuntsen | f2e3ebd | 2019-10-28 16:49:57 +0800 | [diff] [blame] | 240 | print(json.dumps(value)) |
Joel Kitching | 860649d | 2016-11-21 14:53:02 +0800 | [diff] [blame] | 241 | if not success: |
| 242 | sys.exit(1) |
| 243 | |
chuntsen | aabb242 | 2018-03-07 16:16:09 +0800 | [diff] [blame] | 244 | def Archive(self, config_path, data_dir, archive_path, details): |
chuntsen | 65e9f38 | 2018-07-09 18:24:32 +0800 | [diff] [blame] | 245 | """Archives the whole Instalog.""" |
chuntsen | 4cf110a | 2018-02-13 18:35:20 +0800 | [diff] [blame] | 246 | if self._service.IsRunning(): |
| 247 | print('Is the Instalog running? You need to stop the Instalog first') |
| 248 | sys.exit(1) |
| 249 | if os.path.isdir(archive_path): |
| 250 | archive_path = os.path.join(archive_path, 'archived_instalog.tar.gz') |
| 251 | if not os.path.isdir(os.path.dirname(archive_path)): |
| 252 | print('The directory of `%s` does not exist' % |
| 253 | os.path.realpath(archive_path)) |
| 254 | sys.exit(1) |
| 255 | |
| 256 | print('Archiving to %s ...' % os.path.realpath(archive_path)) |
| 257 | with tarfile.open(archive_path, 'w') as tar: |
| 258 | data_dir = os.path.realpath(data_dir) |
| 259 | instalog_dir = instalog_common.INSTALOG_DIR |
| 260 | instalog_parent_dir = instalog_common.INSTALOG_PARENT_DIR |
| 261 | instalog_virtual_env_dir = instalog_common.INSTALOG_VIRTUAL_ENV_DIR |
| 262 | |
| 263 | if os.path.exists(data_dir): |
| 264 | print('Archiving data_dir from %s' % os.path.realpath(data_dir)) |
| 265 | tar.add(data_dir, 'data') |
chuntsen | aabb242 | 2018-03-07 16:16:09 +0800 | [diff] [blame] | 266 | print('Archiving config file from %s' % os.path.realpath(config_path)) |
| 267 | tar.add(config_path, 'instalog.yaml') |
chuntsen | 4cf110a | 2018-02-13 18:35:20 +0800 | [diff] [blame] | 268 | if details >= 1: |
| 269 | def VirtualEnvFilter(tarinfo): |
| 270 | if tarinfo.name == 'instalog/virtual_env': |
| 271 | return None |
| 272 | return tarinfo |
| 273 | print('Archiving Instalog source code') |
| 274 | tar.add(instalog_dir, 'instalog', filter=VirtualEnvFilter) |
| 275 | tar.add(os.path.join(instalog_parent_dir, 'utils'), 'utils') |
| 276 | tar.add(os.path.join(instalog_parent_dir, 'testlog'), 'testlog') |
| 277 | tar.add(os.path.join(instalog_parent_dir, 'external'), 'external') |
| 278 | if details >= 2: |
| 279 | if os.path.exists(instalog_virtual_env_dir): |
| 280 | print('Archiving virtual_env') |
| 281 | tar.add(instalog_virtual_env_dir, 'instalog/virtual_env') |
| 282 | print('DONE') |
| 283 | |
chuntsen | 65e9f38 | 2018-07-09 18:24:32 +0800 | [diff] [blame] | 284 | def Progress(self, plugin_id, details): |
| 285 | """Shows the progress of output plugins""" |
| 286 | progress_dict = self._core.GetAllProgress(details) |
| 287 | for name in sorted(progress_dict): |
| 288 | if plugin_id is None or name.startswith(plugin_id): |
| 289 | completed, total = progress_dict[name] |
| 290 | print('%s completed %d of %d events, and remaining %d events' % |
| 291 | (name, completed, total, total - completed)) |
| 292 | |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 293 | |
Peter Shih | b4e4935 | 2017-05-25 17:35:11 +0800 | [diff] [blame] | 294 | def main(): |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 295 | parser = argparse.ArgumentParser() |
| 296 | parser.add_argument( |
| 297 | '--config', '-c', |
| 298 | help='config file path; by default, searches: \n' |
| 299 | '$PWD/instalog.yaml py/instalog/instalog.yaml ' |
Hung-Te Lin | b0a32bb | 2017-01-05 15:11:06 +0800 | [diff] [blame] | 300 | '~/.instalog.yaml /etc/instalog.yaml /run/instalog.yaml') |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 301 | parser.add_argument( |
| 302 | '--verbose', '-v', action='count', default=0, |
| 303 | help='increase verbosity') |
| 304 | parser.add_argument( |
| 305 | '--quiet', '-q', action='count', default=0, |
| 306 | help='decrease verbosity') |
| 307 | |
| 308 | subparsers = parser.add_subparsers(title='commands') |
| 309 | |
| 310 | start_parser = subparsers.add_parser('start', help='start Instalog') |
| 311 | start_parser.set_defaults(cmd='start') |
| 312 | start_parser.add_argument( |
| 313 | '--no-daemon', '-n', dest='foreground', action='store_true', |
| 314 | help='keep in foreground') |
| 315 | |
| 316 | stop_parser = subparsers.add_parser('stop', help='stop Instalog') |
| 317 | stop_parser.set_defaults(cmd='stop') |
chuntsen | dc33ae8 | 2017-01-17 15:22:16 +0800 | [diff] [blame] | 318 | stop_parser.add_argument( |
| 319 | '--timeout', '-w', type=float, |
| 320 | required=False, default=_DEFAULT_STOP_TIMEOUT, |
| 321 | help='time to wait before giving up') |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 322 | |
| 323 | restart_parser = subparsers.add_parser('restart', help='restart Instalog') |
| 324 | restart_parser.set_defaults(cmd='restart') |
| 325 | |
| 326 | status_parser = subparsers.add_parser('status', help='print Instalog status') |
| 327 | status_parser.set_defaults(cmd='status') |
| 328 | |
Joel Kitching | 2329397 | 2016-11-18 17:24:47 +0800 | [diff] [blame] | 329 | inspect_parser = subparsers.add_parser('inspect', help='inspect plugin store') |
| 330 | inspect_parser.set_defaults(cmd='inspect') |
| 331 | inspect_parser.add_argument( |
| 332 | 'plugin_id', type=str, help='ID of plugin to inspect') |
| 333 | inspect_parser.add_argument( |
| 334 | 'json_path', type=str, nargs='?', default='.', |
| 335 | help='path of store JSON to print') |
| 336 | |
Joel Kitching | 860649d | 2016-11-21 14:53:02 +0800 | [diff] [blame] | 337 | flush_parser = subparsers.add_parser('flush', help='flush plugin') |
| 338 | flush_parser.set_defaults(cmd='flush') |
| 339 | flush_parser.add_argument( |
| 340 | '--timeout', '-w', type=float, |
chuntsen | dc33ae8 | 2017-01-17 15:22:16 +0800 | [diff] [blame] | 341 | required=False, default=_DEFAULT_FLUSH_TIMEOUT, |
Joel Kitching | 860649d | 2016-11-21 14:53:02 +0800 | [diff] [blame] | 342 | help='time to wait before giving up') |
| 343 | flush_parser.add_argument( |
| 344 | 'plugin_id', type=str, nargs='?', default=None, |
| 345 | help='ID of plugin to flush') |
| 346 | |
chuntsen | 4cf110a | 2018-02-13 18:35:20 +0800 | [diff] [blame] | 347 | archive_parser = subparsers.add_parser('archive', help='archive the Instalog') |
| 348 | archive_parser.set_defaults(cmd='archive') |
| 349 | archive_parser.add_argument( |
| 350 | '--output', '-o', dest='archive_path', type=str, |
| 351 | required=False, default='.', |
| 352 | help='path to put the archive file') |
| 353 | archive_parser.add_argument( |
| 354 | '--details', '-d', action='count', default=0, |
| 355 | help='archive more details (instalog code / virtual_env)') |
| 356 | |
chuntsen | 65e9f38 | 2018-07-09 18:24:32 +0800 | [diff] [blame] | 357 | progress_parser = subparsers.add_parser( |
| 358 | 'progress', help='print the progress of plugin') |
| 359 | progress_parser.set_defaults(cmd='progress') |
| 360 | progress_parser.add_argument( |
| 361 | 'plugin_id', type=str, nargs='?', default=None, |
| 362 | help='ID of plugin\'s progress to print') |
| 363 | progress_parser.add_argument( |
| 364 | '--details', '-d', action='count', default=0, |
| 365 | help='print more details') |
| 366 | |
Joel Kitching | 3e72e8b | 2016-07-04 17:03:00 +0800 | [diff] [blame] | 367 | args = parser.parse_args() |
| 368 | |
| 369 | InstalogCLI(args) |
Peter Shih | b4e4935 | 2017-05-25 17:35:11 +0800 | [diff] [blame] | 370 | |
| 371 | if __name__ == '__main__': |
| 372 | main() |