| #!/usr/bin/python2 |
| # |
| # Copyright 2016 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. |
| |
| """Output archive plugin. |
| |
| An archive plugin to backup all events and their attachments to a tar.gz file. |
| |
| The archive name: |
| 'InstalogEvents_' + year + month + day + hour + minute + second |
| |
| The archive structure: |
| InstalogEvents_YYYYmmddHHMMSS.tar.gz |
| InstalogEvents_YYYYmmddHHMMSS/ |
| events.json |
| attachments/ |
| ${ATTACHMENT_0_HASH} |
| ${ATTACHMENT_1_HASH} |
| ${ATTACHMENT_2_HASH} |
| ... |
| """ |
| |
| from __future__ import print_function |
| |
| import datetime |
| import os |
| import shutil |
| import tarfile |
| |
| import instalog_common # pylint: disable=unused-import |
| from instalog import plugin_base |
| from instalog.plugins import output_file |
| from instalog.utils import arg_utils |
| from instalog.utils.arg_utils import Arg |
| from instalog.utils import file_utils |
| |
| |
| class OutputArchive(output_file.OutputFile): |
| |
| ARGS = arg_utils.MergeArgs( |
| output_file.OutputFile.ARGS, |
| [ |
| Arg('enable_disk', bool, |
| 'Whether or not to save the archive to disk. True by default.', |
| default=True), |
| Arg('enable_gcs', bool, |
| 'Whether or not to upload the archive to Google Cloud Storage. ' |
| 'False by default.', |
| default=False), |
| Arg('key_path', (str, unicode), |
| 'Path to Cloud Storage service account JSON key file.', |
| default=None), |
| Arg('gcs_target_dir', (str, unicode), |
| 'Path to the target bucket and directory on Google Cloud ' |
| 'Storage.', |
| default=None), |
| ]) |
| |
| def __init__(self, *args, **kwargs): |
| super(OutputArchive, self).__init__(*args, **kwargs) |
| self._gcs = None |
| |
| def SetUp(self): |
| """Sets up the plugin.""" |
| super(OutputArchive, self).SetUp() |
| if not self.args.enable_disk and not self.args.enable_gcs: |
| raise ValueError('Please enable at least one of "enable_disk" or ' |
| '"enable_gcs"') |
| |
| if not self.args.enable_disk and self.args.target_dir: |
| raise ValueError('If specifying a "target_dir", "enable_disk" must ' |
| 'be set to True') |
| |
| if not self.args.enable_gcs: |
| if self.args.key_path or self.args.gcs_target_dir: |
| raise ValueError('If specifying a "key_path" or "gcs_target_dir", ' |
| '"enable_gcs" must be set to True') |
| if self.args.enable_gcs: |
| if not self.args.key_path or not self.args.gcs_target_dir: |
| raise ValueError('If "enable_gcs" is True, "key_path" and ' |
| '"gcs_target_dir" must be provided') |
| |
| from instalog.utils import gcs_utils |
| self._gcs = gcs_utils.CloudStorage(self.args.key_path) |
| |
| def ProcessEvents(self, base_dir): |
| # Create the archive. |
| cur_time = datetime.datetime.now() |
| archive_name = cur_time.strftime('InstalogEvents_%Y%m%d%H%M%S') |
| archive_filename = '%s.tar.gz' % archive_name |
| with file_utils.UnopenedTemporaryFile( |
| prefix='instalog_archive_', suffix='.tar.gz') as tmp_archive: |
| self.info('Creating temporary archive file: %s', tmp_archive) |
| with tarfile.open(tmp_archive, 'w:gz') as tar: |
| tar.add(base_dir, arcname=archive_name) |
| |
| # What should we do with the archive? |
| if self.args.enable_gcs: |
| gcs_target_dir = self.args.gcs_target_dir.strip('/') |
| gcs_target_path = '/%s/%s' % (gcs_target_dir, archive_filename) |
| if not self._gcs.UploadFile( |
| tmp_archive, gcs_target_path, overwrite=True): |
| self.error('Unable to upload to GCS, aborting') |
| return False |
| if self.args.enable_disk: |
| target_path = os.path.join(self.target_dir, archive_filename) |
| self.info('Saving archive to: %s', target_path) |
| shutil.move(tmp_archive, target_path) |
| return True |
| |
| |
| if __name__ == '__main__': |
| plugin_base.main() |