Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Stefan Countryman, September 14, 2016
3"""
4FileHandlers that upload files to gw-astronomy.org/gwhen and record successful
5uploads with logfile receipts.
6"""
8import logging
9from subprocess import Popen, PIPE
10from llama.filehandler import GenerationError
11from llama.com.utils import UploadReceipt
12from llama.files.skymap_info import SkymapInfo
13from llama.files.lvc_gcn_xml import LvcGcnXml, LvcRetractionXml
14from llama.files.lvalert_json import LVAlertJSON
16LOGGER = logging.getLogger(__name__)
19# The following class is abstract, so we shouldn't need to define abstract
20# methods.
21# pylint: disable=abstract-method
22class GWAstroReceipt(UploadReceipt):
23 """
24 A log file created indicating successful upload of some other original
25 file to gw-astronomy.org.
26 """
28 FILENAME_FMT = "rct_gwa_{}.log"
29 REMOTE_RUNDIR = '/home/gwhen/content/events/'
30 REMOTE_URL = 'gw-astronomy.org'
31 REMOTE_USER = 'gwhen'
32 CLASSNAME_FMT = 'RctGwa{}'
34 @classmethod
35 def set_class_attributes(cls, subclass):
36 """
37 See ``UploadReceipt.set_class_attributes``; this method adds
38 ``SkymapInfo`` to ``subclass.DEPENDENCIES`` if it is not already a
39 member and ``RSYNC_DEST``, the destination directory for uploaded
40 events.
41 """
42 super().set_class_attributes(subclass)
43 if SkymapInfo not in subclass.DEPENDENCIES:
44 subclass.DEPENDENCIES = tuple(subclass.DEPENDENCIES)+(SkymapInfo,)
45 subclass.RSYNC_DEST = (f"{subclass.REMOTE_USER}@{subclass.REMOTE_URL}:"
46 f"{subclass.REMOTE_RUNDIR}")
47 return subclass
49 @property
50 def rsync_source(self):
51 """Get the source path for an ``rsync`` upload to a remote server
52 (including the proper ``--relative`` dot in the path to ensure
53 subdirectory creation serverside)."""
54 return f"{self.rundir}/./{self.eventid}/{self.FILENAME}"
56 def _generate(self): # pylint: disable=arguments-differ
57 cmd = ['rsync', '-rtRv', '--chmod=+r', self.rsync_source,
58 self.RSYNC_DEST]
59 proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
60 res, err = proc.communicate()
61 msg = (f"CMD: {' '.join(cmd)}\nSTDOUT:\n"
62 f"{res.decode()}\nSTDERR:\n{err.decode()}\n")
63 if proc.returncode:
64 LOGGER.error(f"FAILED.\n{msg}")
65 raise GenerationError(msg)
66 with open(self.fullpath, 'w') as outfile:
67 outfile.write(f"SUCCESS.\n{msg}")
70# must register these here to avoid circular imports since SkymapInfo imports
71# them all first
72GWAstroReceipt.upload_this()(SkymapInfo)
73GWAstroReceipt.upload_this()(LvcGcnXml)
74GWAstroReceipt.upload_this()(LvcRetractionXml)
75GWAstroReceipt.upload_this()(LVAlertJSON)